Your cart is currently empty!
Fixing Authentik Email Confirmation OIDC Flow
The Problem
When using Authentik’s default enrollment flow with email confirmation, users who complete email verification are not properly authenticated with your OIDC application. Instead, they get redirected to Authentik’s login page and must enter their credentials again, even though they just completed registration.
Symptoms
- ✅ User completes enrollment form
- ✅ User receives and clicks email confirmation
- ❌ User redirected to login page with “password incorrect” errors
- ❌ Login fails even with correct credentials
- ❌ User cannot authenticate at all after email confirmation
Why This Happens
The default Authentik enrollment flow is designed as a standalone process that doesn’t preserve OIDC authorization context through email confirmation. Here’s what happens:
- User starts OIDC authorization → Redirected to Authentik enrollment
- User completes enrollment → Email verification stage suspends flow
- User clicks email link → Email verification completes
- Flow ends → OIDC context is lost ❌
- User not authenticated in your app → Must login manually
The Solution: Direct OIDC Enrollment Flow
The solution is to modify the enrollment flow so it completes the OIDC authorization directly, without losing context.
Key Changes Required
- Remove redirect stages that break OIDC context
- Configure proper user activation sequence
- End flow with user login stage to complete OIDC authorization
- Preserve OIDC context throughout the entire process
Implementation Guide
Step 1: Export Your Current Enrollment Flow
- Go to Authentik Admin → Flows & Stages → Flows
- Find your enrollment flow (usually “Default enrollment flow”)
- Click Export → Download the YAML file
- Keep this as backup!
Step 2: Create the Fixed Flow Configuration
Create a new file fixed-enrollment-flow.yaml
with the following configuration:
context: {}
entries:
- attrs:
authentication: require_unauthenticated
denied_action: message_continue
designation: enrollment
layout: stacked
name: Fixed OIDC Enrollment Flow
policy_engine_mode: any
title: Welcome to authentik!
conditions: []
identifiers:
pk: da34a483-4eb0-4e9b-b53b-9ce58229a7cf # Use your flow's UUID
slug: default-enrollment-flow # Use your flow's slug
model: authentik_flows.flow
permissions: []
state: present
# Your existing prompt fields (name, email, username, password, etc.)
# ... (keep all your existing prompt configurations)
# CRITICAL: User Write Stage Configuration
- attrs:
create_users_as_inactive: false # Create users as ACTIVE
create_users_group: YOUR_GROUP_UUID
user_creation_mode: always_create
user_path_template: users
user_type: internal
conditions: []
identifiers:
name: default-enrollment-user-write
pk: YOUR_USER_WRITE_STAGE_UUID
model: authentik_stages_user_write.userwritestage
permissions: []
state: present
# Your existing prompt stage bindings
# ... (keep all your existing prompt stage configurations)
# CRITICAL: Email Stage Configuration
- attrs:
activate_user_on_success: true # Activate user on email confirmation
from_address: system@authentik.local
host: localhost
port: 25
subject: authentik
template: email/account_confirmation.html
timeout: 10
token_expiry: minutes=30
use_global_settings: true
conditions: []
identifiers:
name: default-enrollment-email-verification
pk: YOUR_EMAIL_STAGE_UUID
model: authentik_stages_email.emailstage
permissions: []
state: present
# CRITICAL: User Login Stage (MUST be last stage)
- attrs:
geoip_binding: no_binding
network_binding: no_binding
remember_me_offset: seconds=2592000
session_duration: seconds=2592000
conditions: []
identifiers:
name: default-enrollment-user-login
pk: YOUR_LOGIN_STAGE_UUID
model: authentik_stages_user_login.userloginstage
permissions: []
state: present
# Stage Bindings (adjust order numbers as needed)
# ... prompt stages at order 10, 11, etc.
# ... user write stage at order 20
# ... email stage at order 30
# CRITICAL: User login stage at order 100 (LAST)
- attrs:
invalid_response_action: retry
policy_engine_mode: any
re_evaluate_policies: true
conditions: []
identifiers:
order: 100 # MUST be the highest order (last stage)
pk: YOUR_LOGIN_BINDING_UUID
stage: YOUR_LOGIN_STAGE_UUID
target: YOUR_FLOW_UUID
model: authentik_flows.flowstagebinding
permissions: []
state: present
metadata:
labels:
blueprints.goauthentik.io/generated: 'true'
name: Fixed OIDC Enrollment Flow
version: 1
Step 3: Update UUIDs in Your Configuration
You need to replace the placeholder UUIDs with your actual values:
- Get your flow UUID: From your exported flow, find the
pk
under the flow identifiers - Get stage UUIDs: From your exported flow, copy the
pk
values for each stage - Update the configuration with your actual UUIDs
Step 4: Critical Configuration Points
User Write Stage
create_users_as_inactive: false # Users created as ACTIVE
Why: Users must be active to authenticate after email confirmation.
Email Stage
activate_user_on_success: true # Confirms user legitimacy
Why: Ensures email verification activates/confirms the user account.
User Login Stage Position
order: 100 # MUST be the final stage
Why: This stage completes the OIDC authentication and returns tokens to your app.
Step 5: Import the Fixed Flow
- Go to Authentik Admin → Flows & Stages → Flows
- Click Import
- Upload your
fixed-enrollment-flow.yaml
- Verify import success
Step 6: Test the Flow
- Start OIDC login from your application
- Click “Sign Up” to trigger enrollment flow
- Complete enrollment form
- Check email and click confirmation link
- Enter credentials on login page (authentication should now work)
- Verify successful redirect back to your application with authentication
Flow Diagram
User starts OIDC login from your app
↓
Redirected to Authentik enrollment flow
↓
User fills enrollment form (prompts)
↓
User account created (ACTIVE)
↓
Email verification sent
↓
User clicks email confirmation link
↓
Email stage completes successfully
↓
User login stage authenticates user
↓
User redirected to login page (but authentication now WORKS)
↓
User enters credentials and successfully logs in
↓
OIDC tokens generated and returned to your app ✅
Alternative Solutions
Option 1: Custom Email Template (Advanced)
If you prefer to keep redirect stages, you can create a custom email template that preserves OIDC context:
<!-- custom-enrollment-email.html -->
{% extends "email/base.html" %}
{% load i18n %}
{% load humanize %}
{% block content %}
<tr>
<td class="content-block">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="center">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
{% if request.GET.next %}
<a id="confirm" href="{{ url }}&next={{ request.GET.next|urlencode }}"
rel="noopener noreferrer" target="_blank">
{% trans 'Confirm Email' %}
</a>
{% else %}
<a id="confirm" href="{{ url }}"
rel="noopener noreferrer" target="_blank">
{% trans 'Confirm Email' %}
</a>
{% endif %}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
{% endblock %}
Option 2: Redirect Stage Approach (Complex)
You can use a redirect stage to transfer from enrollment to authentication flow, but this requires:
- Redirect stage configuration:
- attrs: target_flow: YOUR_AUTH_FLOW_UUID keep_context: true mode: flow
- Proper UUID references
- Context preservation settings
Note: The direct approach (recommended solution) is simpler and more reliable.
Troubleshooting
Issue: “Password incorrect” after email confirmation
Cause: User created as inactive Solution: Set create_users_as_inactive: false
Issue: User redirected to login page after email confirmation
Expected Behavior: User should be able to log in successfully with their credentials Solution: This is normal behavior – the fix ensures authentication works after email confirmation
Issue: Flow import fails with UUID errors
Cause: Using placeholder UUIDs Solution: Replace all UUIDs with your actual flow/stage UUIDs
Issue: Email confirmation link doesn’t work
Cause: Email stage misconfiguration Solution: Verify activate_user_on_success: true
and email settings
Issue: User not authenticated in your application
Cause: OIDC tokens not returned Solution: Verify user login stage completes the flow
Security Considerations
User Activation Strategy
Recommended: create_users_as_inactive: false
+ activate_user_on_success: true
- Users are created active but must verify email to complete OIDC flow
- Provides security through email verification requirement
- Allows seamless authentication after confirmation
Alternative: create_users_as_inactive: true
+ activate_user_on_success: true
- Users inactive until email verification
- Slightly more secure but same end result for OIDC flows
Email Verification
- Email verification is required for OIDC completion
- Users cannot get application tokens without confirming email
- Unverified users cannot complete the enrollment flow
Common Pitfalls
- Wrong stage order: User login stage must be last
- Missing UUIDs: Must use actual UUIDs, not placeholders
- Inactive users: Must create users as active or activate on email success
- Flow context loss: Using redirect stages incorrectly
- Multiple flows: Ensure you’re modifying the correct enrollment flow
Best Practices
- Always backup your original flow before modifications
- Test thoroughly in a non-production environment first
- Use descriptive flow names to distinguish fixed flows
- Monitor logs during testing for error details
- Document your changes for future reference
Conclusion
The direct OIDC enrollment approach eliminates the authentication failures that plague the default Authentik enrollment flow. By properly configuring user activation and stage sequencing, users get a working registration → email verification → login experience.
Key improvement: After email confirmation, users are redirected to the login page where their credentials actually work (instead of failing with “password incorrect” errors). Once they log in, they’re successfully authenticated with your OIDC application.
This solution has been tested and works reliably for OIDC applications that require email verification during user enrollment.
Questions or Issues?
- Check Authentik logs for detailed error messages
- Verify all UUIDs are correct in your configuration
- Ensure your OIDC application settings are correct
- Test with a fresh user account
Contributing If you find improvements to this guide or encounter edge cases, please contribute back to help other developers facing this common issue.
by
Tags:
Leave a Reply