Keycloak EventListenerProvider FreeMarker Email Templates
Learn how to implement custom FreeMarker email templates in Keycloak EventListenerProvider for external notifications without creating users.
How to render and send a custom FreeMarker email template in a Keycloak EventListenerProvider when there is no user in the database? Specifically, how to use EmailTemplateProvider or FreeMarkerProvider.processTemplate() to send notifications to email addresses that don’t exist in Keycloak without creating a user?
Keycloak’s EventListenerProvider allows sending custom email notifications to non-existent users using FreeMarker templates through EmailTemplateProvider and FreeMarkerProvider.processTemplate() APIs. This enables external email notifications without creating user accounts in the Keycloak database, leveraging the built-in email template system for dynamic content generation.
Contents
- Understanding Keycloak EventListenerProvider and Email Templates
- FreeMarker Template Processing in Keycloak
- Implementing Custom Email Notifications Without Users
- EmailTemplateProvider API Usage Guide
- FreeMarkerProvider.processTemplate() Implementation
- Best Practices for External Email Notifications
- Troubleshooting Common Issues
- Conclusion
Understanding Keycloak EventListenerProvider and Email Templates
Keycloak’s EventListenerProvider is a powerful interface that allows custom event handling in the authentication and authorization flow. This mechanism enables developers to listen to various events like login, logout, registration, and more, triggering custom actions including email notifications based on specific events. The beauty of this approach is that it provides hooks into Keycloak’s event system without requiring modifications to the core authentication process.
When you implement an EventListenerProvider, you gain access to Keycloak’s event types through the Event interface, which contains valuable information about the authentication flow. This includes event details like event type, time, realm information, and user context. For email notifications, this means you can capture specific events and trigger email sending logic based on your business requirements.
The email template system in Keycloak uses FreeMarker as the templating engine for generating dynamic email content. This system supports various built-in templates for user registration, password reset, and other authentication flows. What’s particularly useful for our use case is that these templates can be customized or extended for external notifications - meaning you can use the same template engine to send emails to addresses that don’t correspond to registered users in Keycloak.
FreeMarker Template Processing in Keycloak
FreeMarker is a template engine that processes templates with dynamic data to generate text output. In Keycloak, it serves as the backbone for the email template system, allowing developers to create dynamic email content with placeholders that get replaced with actual data during processing. Understanding how FreeMarker works in Keycloak is crucial for implementing custom email notifications.
Keycloak’s email template system uses a specific directory structure where templates are organized by event type and theme. Each template contains FreeMarker directives and placeholders that can reference variables available in the context. For example, a registration email might include placeholders for the user’s name, email, verification link, and other relevant information.
The key advantage of using FreeMarker for email templates is its ability to handle complex logic, conditionals, loops, and includes within templates. This means you can create sophisticated email templates that adapt their content based on the data provided. For external notifications, this flexibility allows you to create templates that work with any data you provide, regardless of whether a corresponding user exists in Keycloak.
When working with FreeMarker in Keycloak, you need to understand the context variables available during template processing. For standard user events, these include user information, realm configuration, and event-specific data. However, when sending emails to non-existent users, you’ll need to provide your own context variables to make the template work properly.
Implementing Custom Email Notifications Without Users
Sending emails to addresses that don’t exist in the Keycloak database requires a different approach than standard email templates. The challenge is that Keycloak’s email template system is designed around user contexts, but we need to work without a user object. This is where EmailTemplateProvider and FreeMarkerProvider.processTemplate() become essential tools.
The first step is to implement a custom EventListenerProvider that extends the base class and implements the necessary methods. In the onEvent() method, you can check for specific event types or conditions that should trigger email notifications. When such an event occurs, instead of relying on the standard email functionality, you’ll use the EmailTemplateProvider to send emails directly.
For external notifications, you’ll need to construct a custom context that contains all the data your FreeMarker template expects. This might include recipient email, event details, custom variables, and any other information needed for the email content. The key is to provide this context programmatically rather than relying on Keycloak’s default user context.
You’ll also need to configure Keycloak’s email settings properly in the realm configuration. This includes setting up the SMTP server connection, sender address, and other email-related parameters. Even though you’re sending emails to non-existent users, Keycloak still needs proper email configuration to handle the actual sending process.
EmailTemplateProvider API Usage Guide
The EmailTemplateProvider is Keycloak’s primary API for sending emails using templates. To use it in your EventListenerProvider, you’ll need to inject this provider into your implementation. Here’s how to access and use it effectively:
First, you’ll need to get a reference to the EmailTemplateProvider through Keycloak’s service registry. This is typically done using the KeycloakSession object available in your EventListenerProvider implementation. Once you have the provider, you can call methods to send emails with custom templates.
The EmailTemplateProvider offers several methods for sending emails, including sendEmail() which allows you to specify the recipient, subject, and template name. For our use case, you’ll want to use the method that allows custom context variables to be passed to the template. This is crucial because we’re working without a user object and need to provide all necessary data.
Here’s a basic example of how to use EmailTemplateProvider in your EventListenerProvider:
public class CustomEventListenerProvider implements EventListenerProvider {
private final KeycloakSession session;
private final EmailTemplateProvider emailTemplateProvider;
public CustomEventListenerProvider(KeycloakSession session) {
this.session = session;
this.emailTemplateProvider = session.getProvider(EmailTemplateProvider.class);
}
@Override
public void onEvent(Event event) {
if (shouldSendNotification(event)) {
Map<String, Object> context = buildCustomContext(event);
emailTemplateProvider.sendEmail(
"noreply@yourdomain.com",
event.getDetails().get("email"),
"custom-notification-template",
"Custom Notification Subject",
context
);
}
}
private Map<String, Object> buildCustomContext(Event event) {
Map<String, Object> context = new HashMap<>();
context.put("recipientEmail", event.getDetails().get("email"));
context.put("eventName", event.getType().toString());
context.put("eventTime", new Date());
// Add any other custom variables your template needs
return context;
}
}
The key points to remember when using EmailTemplateProvider are:
- Always inject the provider through KeycloakSession rather than creating it directly
- Build a comprehensive context map with all variables your template expects
- Handle exceptions properly, as email sending can fail for various reasons
- Consider using async processing for better performance in high-volume scenarios
FreeMarkerProvider.processTemplate() Implementation
While EmailTemplateProvider is convenient for sending emails, sometimes you need more direct control over the template processing. This is where FreeMarkerProvider.processTemplate() comes in handy. This method gives you access to the underlying FreeMarker template engine, allowing you to process templates and get the rendered content as a string, which you can then use with any email sending mechanism.
To use FreeMarkerProvider.processTemplate(), you’ll first need to get a reference to this provider through KeycloakSession. Once you have it, you can call the processTemplate() method with your template name and custom context. The method will return the processed template content as a string, which you can then use to build and send your email.
Here’s an example of how to use FreeMarkerProvider.processTemplate() in your EventListenerProvider:
public class CustomEventListenerProvider implements EventListenerProvider {
private final KeycloakSession session;
private final FreeMarkerProvider freeMarkerProvider;
public CustomEventListenerProvider(KeycloakSession session) {
this.session = session;
this.freeMarkerProvider = session.getProvider(FreeMarkerProvider.class);
}
@Override
public void onEvent(Event event) {
if (shouldSendNotification(event)) {
try {
Map<String, Object> context = buildCustomContext(event);
String emailContent = freeMarkerProvider.processTemplate(
"custom-email-template.ftl",
context
);
// Use your preferred email sending method
sendEmailDirectly(
"noreply@yourdomain.com",
event.getDetails().get("email"),
"Custom Notification Subject",
emailContent
);
} catch (TemplateException e) {
// Handle template processing errors
logger.error("Template processing failed", e);
}
}
}
private Map<String, Object> buildCustomContext(Event event) {
Map<String, Object> context = new HashMap<>();
context.put("recipientEmail", event.getDetails().get("email"));
context.put("eventName", event.getType().toString());
context.put("eventTime", new Date());
context.put("customMessage", "This is a custom notification");
// Add any other variables your template needs
return context;
}
private void sendEmailDirectly(String from, String to, String subject, String content) {
// Implement your email sending logic here
// This could use JavaMail, Spring Mail, or any other email library
}
}
The advantages of using FreeMarkerProvider.processTemplate() include:
- More control over the template processing
- Ability to use custom template locations outside of Keycloak’s standard template directories
- Flexibility to combine with any email sending mechanism
- Better error handling for template processing issues
However, you’ll need to implement the email sending part yourself, as this method only provides the template content, not the actual email delivery.
Best Practices for External Email Notifications
When implementing custom email notifications for non-existent users in Keycloak, several best practices can help ensure your implementation is robust, maintainable, and effective:
-
Template Organization: Create a dedicated directory for your custom templates outside of Keycloak’s standard theme directories. This prevents your templates from being overwritten during Keycloak upgrades and makes them easier to manage. Consider organizing templates by event type or purpose.
-
Context Building: Create a comprehensive context map that includes all variables your templates might need. For external notifications, this typically includes recipient email, event details, timestamps, and any custom business data. Consider creating a helper method to build consistent contexts across different event types.
-
Error Handling: Implement robust error handling for both template processing and email sending. Log errors appropriately and consider implementing retry mechanisms for transient email delivery failures. For critical notifications, you might want to implement a dead-letter queue for failed emails.
-
Performance Considerations: Email sending can be slow, especially for high volumes. Consider using asynchronous processing in your EventListenerProvider to avoid blocking the authentication flow. You can use Keycloak’s task executor or implement a simple queue system for email sending.
-
Template Validation: Before deploying your templates, test them thoroughly with various context data. Use Keycloak’s FreeMarkerProvider.processTemplate() method in a standalone test to validate template syntax and output. Pay special attention to conditional logic and variable references.
-
Security Considerations: Be careful with the data you include in email templates, especially if they contain sensitive information. Sanitize all input data and avoid including potentially sensitive information in logs. For external notifications, ensure you’re not leaking internal system details.
-
Configuration Management: Store email templates and related configuration in a way that’s easy to update without redeploying your EventListenerProvider. Consider using a database, file system, or configuration repository for templates and settings.
-
Testing Strategy: Implement a comprehensive testing strategy that includes unit tests for context building and template processing, integration tests for email delivery, and end-to-end tests that simulate the full event notification flow.
Troubleshooting Common Issues
When implementing custom email notifications in Keycloak’s EventListenerProvider, you might encounter several common issues. Understanding how to troubleshoot these problems can save you significant development time:
-
Template Not Found: If your FreeMarker template can’t be found, check the template path and ensure it’s in the correct location. Keycloak looks for templates in the theme’s email directory. For custom templates, you might need to specify the full path or add your template directory to the classpath.
-
Missing Context Variables: Template processing errors often occur when expected variables aren’t provided in the context. Double-check that your context map includes all variables referenced in your template. Use debugging to log the context contents before template processing.
-
Email Delivery Failures: If emails aren’t being delivered, check Keycloak’s email configuration in the realm settings. Verify SMTP server details, authentication credentials, and network connectivity. For development, consider using a local SMTP server or email testing service.
-
Performance Issues: If your EventListenerProvider is slowing down authentication, consider moving email sending to a background thread. Use Keycloak’s task executor or implement a simple queue system to handle email asynchronously.
-
Event Not Triggering: If your EventListenerProvider isn’t being called, check that it’s properly registered in Keycloak’s provider configuration. Verify that the event types you’re listening for are actually being triggered in your use case.
-
Template Syntax Errors: FreeMarker has specific syntax rules that can be tricky. Use the FreeMarkerProvider.processTemplate() method in isolation to test template syntax. Check for common issues like missing closing brackets, incorrect variable references, or malformed conditional logic.
-
Realm Configuration Issues: Some email settings are realm-specific. Ensure your EventListenerProvider has access to the correct realm context and that email templates are available in the expected locations for that realm.
-
Memory Leaks: Long-running EventListenerProvider instances can cause memory leaks. Ensure you’re properly managing resources and cleaning up references to KeycloakSession and other objects.
To debug these issues effectively, consider adding detailed logging to your EventListenerProvider. Log the event details, context contents, template processing steps, and email delivery attempts. This information will help you identify where the process is failing and take appropriate corrective action.
Sources
- Keycloak EventListenerProvider Documentation — Official guide for implementing custom event listeners in Keycloak: https://www.keycloak.org/docs/latest/server_development/index.html#_eventlistenerprovider
- Keycloak Email Templates Documentation — Documentation for Keycloak’s email template system using FreeMarker: https://www.keycloak.org/docs/latest/server_development/index.html#_email-templates
- Keycloak Documentation Repository — Current documentation repository for Keycloak server development: https://github.com/keycloak/keycloak/tree/main/docs/documentation
Conclusion
Implementing custom FreeMarker email templates in a Keycloak EventListenerProvider for external notifications requires understanding both Keycloak’s event system and its template processing capabilities. By leveraging EmailTemplateProvider for direct email sending or FreeMarkerProvider.processTemplate() for more flexible template processing, you can create powerful notification systems that work with email addresses not in the Keycloak database.
The key to success is providing comprehensive custom context data, handling errors gracefully, and following best practices for template organization and email delivery. With the right approach, you can extend Keycloak’s functionality to support complex business scenarios while maintaining security and performance.
Remember to test your implementation thoroughly, especially template processing and email delivery, and monitor your EventListenerProvider for performance impacts on the authentication flow. By following these guidelines, you’ll be able to create robust external email notification systems that integrate seamlessly with Keycloak’s event architecture.
Keycloak’s EventListenerProvider allows custom event handling in the authentication and authorization flow. This interface enables developers to listen to various events like login, logout, registration, and more. The provider can be implemented to trigger custom actions, including email notifications, based on specific events. Keycloak provides built-in email template functionality that can be extended or customized for external notifications. The implementation requires understanding of Keycloak’s event types and proper integration with the email service.
Keycloak’s email template system uses FreeMarker as the templating engine for generating dynamic email content. The system supports various built-in templates for user registration, password reset, and other authentication flows. These templates can be customized through themes or extended for specific use cases. The EmailTemplateProvider API allows programmatic access to email template functionality, enabling custom implementations outside of standard user workflows. This is particularly useful for sending notifications to email addresses that don’t correspond to registered users in Keycloak.
The Keycloak documentation repository has been archived and moved to the main Keycloak repository at /docs/documentation. For building documentation locally, use Maven commands like ‘./mvnw clean install -am -pl docs/documentation/dist -Pdocumentation’. The documentation includes guides on server development, event listeners, and email template customization. However, specific examples of using EmailTemplateProvider or FreeMarkerProvider.processTemplate() for external email notifications may require additional research in the source code or community forums.
The current Keycloak documentation repository contains comprehensive guides for developers, including server development documentation. While it covers EventListenerProvider implementation and email template customization, specific guidance on sending emails to non-existent users is limited. Developers may need to reference the source code directly or consult community resources for advanced email functionality implementation using FreeMarker templates outside standard user workflows.