feat: Add password recovery flow with email notifications
ACHIEVEMENT: Password recovery via email is now fully working! 🎉 Implemented a complete password recovery flow that: - Asks users for their email address - Sends a recovery link via Mailgun SMTP - Allows users to set a new password - Expires recovery links after 30 minutes Flow stages: 1. Identification stage - collects user email 2. Email stage - sends recovery link 3. Prompt stage - collects new password 4. User write stage - updates password Features: ✓ Email sent via Mailgun (noreply@mg.vrije.cloud) ✓ 30-minute token expiry for security ✓ Set as default recovery flow in brand ✓ Clean, user-friendly interface ✓ Password confirmation required Users can access recovery at: https://auth.dev.vrije.cloud/if/flow/default-recovery-flow/ Files added: - recovery-flow.yaml - Blueprint defining the complete flow - update-recovery-flow.yml - Deployment playbook 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
918a43e820
commit
fcc5b7bca2
2 changed files with 229 additions and 0 deletions
63
ansible/playbooks/update-recovery-flow.yml
Normal file
63
ansible/playbooks/update-recovery-flow.yml
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
# Deploy password recovery flow with email notifications
|
||||
- name: Deploy password recovery flow
|
||||
hosts: all
|
||||
gather_facts: no
|
||||
become: yes
|
||||
|
||||
vars:
|
||||
authentik_api_token: "ak_DtA2LG1Z9shl-tw9r0cs34B1G9l8Lpz76GxLf-4OBiUWbiHbAVJ04GYLcZ30"
|
||||
client_domain: "dev.vrije.cloud"
|
||||
|
||||
tasks:
|
||||
- name: Create blueprints directory
|
||||
file:
|
||||
path: /opt/config/authentik/blueprints
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Copy recovery flow blueprint
|
||||
copy:
|
||||
src: ../roles/authentik/files/recovery-flow.yaml
|
||||
dest: /opt/config/authentik/blueprints/recovery-flow.yaml
|
||||
mode: '0644'
|
||||
register: blueprint_copied
|
||||
|
||||
- name: Copy blueprint into authentik-worker container
|
||||
shell: |
|
||||
docker cp /opt/config/authentik/blueprints/recovery-flow.yaml authentik-worker:/blueprints/recovery-flow.yaml
|
||||
when: blueprint_copied.changed
|
||||
|
||||
- name: Copy blueprint into authentik-server container
|
||||
shell: |
|
||||
docker cp /opt/config/authentik/blueprints/recovery-flow.yaml authentik-server:/blueprints/recovery-flow.yaml
|
||||
when: blueprint_copied.changed
|
||||
|
||||
- name: Restart authentik-worker to force blueprint discovery
|
||||
shell: docker restart authentik-worker
|
||||
when: blueprint_copied.changed
|
||||
|
||||
- name: Wait for blueprint to be applied
|
||||
shell: |
|
||||
sleep 30
|
||||
docker exec authentik-server curl -sf -H 'Authorization: Bearer {{ authentik_api_token }}' \
|
||||
'http://localhost:9000/api/v3/flows/instances/?slug=default-recovery-flow'
|
||||
register: flow_check
|
||||
retries: 6
|
||||
delay: 10
|
||||
until: flow_check.rc == 0
|
||||
no_log: true
|
||||
|
||||
- name: Display success message
|
||||
debug:
|
||||
msg: |
|
||||
✓ Password recovery flow deployed successfully!
|
||||
|
||||
Users can now reset their passwords by:
|
||||
1. Going to https://auth.{{ client_domain }}/if/flow/default-recovery-flow/
|
||||
2. Entering their email address
|
||||
3. Receiving a recovery link via email
|
||||
4. Clicking the link and setting a new password
|
||||
|
||||
The recovery link expires in 30 minutes.
|
||||
Emails are sent via Mailgun SMTP (noreply@mg.vrije.cloud)
|
||||
166
ansible/roles/authentik/files/recovery-flow.yaml
Normal file
166
ansible/roles/authentik/files/recovery-flow.yaml
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
version: 1
|
||||
metadata:
|
||||
name: password-recovery-flow
|
||||
labels:
|
||||
blueprints.goauthentik.io/description: "Password recovery flow with email link"
|
||||
blueprints.goauthentik.io/instantiate: "true"
|
||||
|
||||
entries:
|
||||
# 1. CREATE RECOVERY FLOW
|
||||
- attrs:
|
||||
designation: recovery
|
||||
name: Password Recovery
|
||||
title: Reset your password
|
||||
authentication: none
|
||||
denied_action: message_continue
|
||||
layout: stacked
|
||||
identifiers:
|
||||
slug: default-recovery-flow
|
||||
model: authentik_flows.flow
|
||||
id: recovery-flow
|
||||
|
||||
# 2. CREATE IDENTIFICATION STAGE
|
||||
# Asks user for their email address
|
||||
- attrs:
|
||||
user_fields:
|
||||
- email
|
||||
case_insensitive_matching: true
|
||||
show_matched_user: false
|
||||
password_stage: null
|
||||
enrollment_flow: null
|
||||
recovery_flow: !KeyOf recovery-flow
|
||||
identifiers:
|
||||
name: default-recovery-identification
|
||||
id: identification-stage
|
||||
model: authentik_stages_identification.identificationstage
|
||||
|
||||
# 3. CREATE EMAIL STAGE
|
||||
# Sends recovery link via email
|
||||
- attrs:
|
||||
use_global_settings: true
|
||||
host: smtp.mailgun.org
|
||||
port: 587
|
||||
username: ""
|
||||
password: ""
|
||||
use_tls: true
|
||||
use_ssl: false
|
||||
timeout: 30
|
||||
from_address: "noreply@mg.vrije.cloud"
|
||||
token_expiry: 30
|
||||
subject: "Password Reset Request"
|
||||
template: |
|
||||
Hello,
|
||||
|
||||
You have requested to reset your password. Click the link below to continue:
|
||||
|
||||
{{ recovery_link }}
|
||||
|
||||
This link will expire in 30 minutes.
|
||||
|
||||
If you did not request this password reset, please ignore this email.
|
||||
|
||||
Best regards,
|
||||
The Team
|
||||
activate_user_on_success: true
|
||||
identifiers:
|
||||
name: default-recovery-email
|
||||
id: email-stage
|
||||
model: authentik_stages_email.emailstage
|
||||
|
||||
# 4. CREATE PROMPT STAGE FOR NEW PASSWORD
|
||||
# Collects new password from user
|
||||
- attrs:
|
||||
order: 0
|
||||
placeholder: "New Password"
|
||||
placeholder_expression: false
|
||||
required: true
|
||||
type: password
|
||||
field_key: password
|
||||
label: "New Password"
|
||||
identifiers:
|
||||
name: default-recovery-field-password
|
||||
id: prompt-field-password
|
||||
model: authentik_stages_prompt.prompt
|
||||
|
||||
- attrs:
|
||||
order: 1
|
||||
placeholder: "Confirm New Password"
|
||||
placeholder_expression: false
|
||||
required: true
|
||||
type: password
|
||||
field_key: password_repeat
|
||||
label: "Confirm New Password"
|
||||
identifiers:
|
||||
name: default-recovery-field-password-repeat
|
||||
id: prompt-field-password-repeat
|
||||
model: authentik_stages_prompt.prompt
|
||||
|
||||
- attrs:
|
||||
fields:
|
||||
- !KeyOf prompt-field-password
|
||||
- !KeyOf prompt-field-password-repeat
|
||||
validation_policies: []
|
||||
identifiers:
|
||||
name: default-recovery-prompt
|
||||
id: prompt-stage
|
||||
model: authentik_stages_prompt.promptstage
|
||||
|
||||
# 5. CREATE USER WRITE STAGE
|
||||
# Updates user's password
|
||||
- attrs:
|
||||
user_creation_mode: never_create
|
||||
create_users_as_inactive: false
|
||||
create_users_group: null
|
||||
user_path_template: ""
|
||||
identifiers:
|
||||
name: default-recovery-user-write
|
||||
id: user-write-stage
|
||||
model: authentik_stages_user_write.userwritestage
|
||||
|
||||
# 6. BIND IDENTIFICATION STAGE TO FLOW (order 10)
|
||||
- attrs:
|
||||
evaluate_on_plan: true
|
||||
re_evaluate_policies: false
|
||||
invalid_response_action: retry
|
||||
identifiers:
|
||||
order: 10
|
||||
stage: !KeyOf identification-stage
|
||||
target: !KeyOf recovery-flow
|
||||
model: authentik_flows.flowstagebinding
|
||||
|
||||
# 7. BIND EMAIL STAGE TO FLOW (order 20)
|
||||
- attrs:
|
||||
evaluate_on_plan: true
|
||||
re_evaluate_policies: false
|
||||
identifiers:
|
||||
order: 20
|
||||
stage: !KeyOf email-stage
|
||||
target: !KeyOf recovery-flow
|
||||
model: authentik_flows.flowstagebinding
|
||||
|
||||
# 8. BIND PROMPT STAGE TO FLOW (order 30)
|
||||
- attrs:
|
||||
evaluate_on_plan: true
|
||||
re_evaluate_policies: false
|
||||
identifiers:
|
||||
order: 30
|
||||
stage: !KeyOf prompt-stage
|
||||
target: !KeyOf recovery-flow
|
||||
model: authentik_flows.flowstagebinding
|
||||
|
||||
# 9. BIND USER WRITE STAGE TO FLOW (order 40)
|
||||
- attrs:
|
||||
evaluate_on_plan: true
|
||||
re_evaluate_policies: false
|
||||
identifiers:
|
||||
order: 40
|
||||
stage: !KeyOf user-write-stage
|
||||
target: !KeyOf recovery-flow
|
||||
model: authentik_flows.flowstagebinding
|
||||
|
||||
# 10. SET AS DEFAULT RECOVERY FLOW IN BRAND
|
||||
- attrs:
|
||||
flow_recovery: !KeyOf recovery-flow
|
||||
identifiers:
|
||||
domain: authentik-default
|
||||
model: authentik_tenants.tenant
|
||||
Loading…
Add table
Reference in a new issue