Merge pull request #92 from christianlouis/copilot/fix-login-and-profile-management
Fix profile page: use Logto Account Center prebuilt flows for password change and MFA
This commit is contained in:
@@ -7,8 +7,10 @@ GET /sign-in – Initiate the Logto sign-in flow.
|
|||||||
GET /callback – Handle the Logto authorization-code callback.
|
GET /callback – Handle the Logto authorization-code callback.
|
||||||
GET /sign-out – Sign the user out (clears session + redirects to Logto).
|
GET /sign-out – Sign the user out (clears session + redirects to Logto).
|
||||||
GET /me – Return the currently authenticated user's profile.
|
GET /me – Return the currently authenticated user's profile.
|
||||||
GET /forgot-password – Redirect to Logto's forgot-password screen.
|
GET /forgot-password – Redirect to Logto's forgot-password screen (unauthenticated).
|
||||||
GET /account-portal – Redirect to the Logto account portal (MFA management).
|
GET /change-password – Redirect to Logto Account Center password page (authenticated).
|
||||||
|
GET /manage-mfa – Redirect to Logto Account Center MFA page (authenticated).
|
||||||
|
GET /account-portal – Redirect to the Logto Account Center root.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
@@ -199,6 +201,24 @@ async def sign_out(request: Request) -> RedirectResponse:
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/change-password")
|
||||||
|
async def change_password(request: Request) -> RedirectResponse:
|
||||||
|
"""
|
||||||
|
Redirect an authenticated user to the Logto Account Center password page.
|
||||||
|
|
||||||
|
Uses Logto's prebuilt Account Center flow at ``{LOGTO_ENDPOINT}/account/password``
|
||||||
|
so the user can change their existing password directly. A ``redirect``
|
||||||
|
query parameter is appended so that Logto returns the user to the Profile &
|
||||||
|
Security page after a successful update.
|
||||||
|
"""
|
||||||
|
if not settings.logto_configured:
|
||||||
|
raise _logto_not_configured()
|
||||||
|
|
||||||
|
base = str(request.base_url).rstrip("/")
|
||||||
|
password_url = f"{settings.LOGTO_ENDPOINT.rstrip('/')}/account/password?redirect={base}/profile"
|
||||||
|
return RedirectResponse(url=password_url, status_code=302)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/forgot-password")
|
@router.get("/forgot-password")
|
||||||
async def forgot_password(request: Request) -> RedirectResponse:
|
async def forgot_password(request: Request) -> RedirectResponse:
|
||||||
"""
|
"""
|
||||||
@@ -209,6 +229,9 @@ async def forgot_password(request: Request) -> RedirectResponse:
|
|||||||
password-reset form immediately instead of the normal sign-in form.
|
password-reset form immediately instead of the normal sign-in form.
|
||||||
After the user resets their password they are returned via the normal
|
After the user resets their password they are returned via the normal
|
||||||
callback flow and land on the app dashboard.
|
callback flow and land on the app dashboard.
|
||||||
|
|
||||||
|
This endpoint is kept for unauthenticated / "I forgot my password" use
|
||||||
|
cases. Authenticated users should use ``/change-password`` instead.
|
||||||
"""
|
"""
|
||||||
if not settings.logto_configured:
|
if not settings.logto_configured:
|
||||||
raise _logto_not_configured()
|
raise _logto_not_configured()
|
||||||
@@ -229,20 +252,44 @@ async def forgot_password(request: Request) -> RedirectResponse:
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/account-portal")
|
@router.get("/manage-mfa")
|
||||||
async def account_portal(request: Request) -> RedirectResponse:
|
async def manage_mfa(request: Request) -> RedirectResponse:
|
||||||
"""
|
"""
|
||||||
Redirect an authenticated user to the Logto account portal.
|
Redirect an authenticated user to the Logto Account Center MFA page.
|
||||||
|
|
||||||
The Logto account portal (``{LOGTO_ENDPOINT}/account``) lets users manage
|
Uses Logto's prebuilt Account Center flow at
|
||||||
their profile, linked identities, and multi-factor authentication settings
|
``{LOGTO_ENDPOINT}/account/authenticator-app`` so the user can enable,
|
||||||
without leaving the Logto-hosted UI. After updating their settings, users
|
configure, or remove TOTP authenticator-app MFA directly. A ``redirect``
|
||||||
can simply navigate back to the app.
|
query parameter is appended so that Logto returns the user to the Profile &
|
||||||
|
Security page after a successful update.
|
||||||
"""
|
"""
|
||||||
if not settings.logto_configured:
|
if not settings.logto_configured:
|
||||||
raise _logto_not_configured()
|
raise _logto_not_configured()
|
||||||
|
|
||||||
portal_url = f"{settings.LOGTO_ENDPOINT.rstrip('/')}/account"
|
base = str(request.base_url).rstrip("/")
|
||||||
|
mfa_url = (
|
||||||
|
f"{settings.LOGTO_ENDPOINT.rstrip('/')}/account/authenticator-app"
|
||||||
|
f"?redirect={base}/profile"
|
||||||
|
)
|
||||||
|
return RedirectResponse(url=mfa_url, status_code=302)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/account-portal")
|
||||||
|
async def account_portal(request: Request) -> RedirectResponse:
|
||||||
|
"""
|
||||||
|
Redirect an authenticated user to the Logto Account Center.
|
||||||
|
|
||||||
|
The Logto account portal (``{LOGTO_ENDPOINT}/account``) lets users manage
|
||||||
|
their profile, linked identities, and multi-factor authentication settings
|
||||||
|
without leaving the Logto-hosted UI. A ``redirect`` query parameter is
|
||||||
|
appended so that Logto returns the user to the Profile & Security page
|
||||||
|
after a successful update.
|
||||||
|
"""
|
||||||
|
if not settings.logto_configured:
|
||||||
|
raise _logto_not_configured()
|
||||||
|
|
||||||
|
base = str(request.base_url).rstrip("/")
|
||||||
|
portal_url = f"{settings.LOGTO_ENDPOINT.rstrip('/')}/account?redirect={base}/profile"
|
||||||
return RedirectResponse(url=portal_url, status_code=302)
|
return RedirectResponse(url=portal_url, status_code=302)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -76,28 +76,28 @@
|
|||||||
{% call card_header() %}
|
{% call card_header() %}
|
||||||
{% call card_title() %}Account Security{% endcall %}
|
{% call card_title() %}Account Security{% endcall %}
|
||||||
{% call card_description() %}
|
{% call card_description() %}
|
||||||
Manage your password and multi-factor authentication settings.
|
Manage your password and multi-factor authentication settings
|
||||||
These actions redirect you to your Logto identity account.
|
via the Logto account center.
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
{% call card_content() %}
|
{% call card_content() %}
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
|
|
||||||
<!-- Password reset -->
|
<!-- Password change -->
|
||||||
<div class="flex items-start justify-between gap-4">
|
<div class="flex items-start justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<p class="font-medium">Password</p>
|
<p class="font-medium">Password</p>
|
||||||
<p class="text-sm text-base-content/60">
|
<p class="text-sm text-base-content/60">
|
||||||
Reset your Logto account password via email verification.
|
Change your password in the Logto account center.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% call button_link(href='/api/v1/auth/forgot-password', variant='outline', size='sm') %}
|
{% call button_link(href='/api/v1/auth/change-password', variant='outline', size='sm') %}
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 mr-1" fill="none"
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 mr-1" fill="none"
|
||||||
viewBox="0 0 24 24" stroke="currentColor">
|
viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/>
|
d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/>
|
||||||
</svg>
|
</svg>
|
||||||
Reset Password
|
Change Password
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -109,10 +109,10 @@
|
|||||||
<p class="font-medium">Multi-Factor Authentication</p>
|
<p class="font-medium">Multi-Factor Authentication</p>
|
||||||
<p class="text-sm text-base-content/60">
|
<p class="text-sm text-base-content/60">
|
||||||
Enable, configure, or remove MFA methods such as TOTP
|
Enable, configure, or remove MFA methods such as TOTP
|
||||||
authenticator apps and backup codes in your Logto account portal.
|
authenticator apps and backup codes in your Logto account center.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% call button_link(href='/api/v1/auth/account-portal', variant='outline', size='sm') %}
|
{% call button_link(href='/api/v1/auth/manage-mfa', variant='outline', size='sm') %}
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 mr-1" fill="none"
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 mr-1" fill="none"
|
||||||
viewBox="0 0 24 24" stroke="currentColor">
|
viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
|||||||
Reference in New Issue
Block a user