Rewrite auth layer to use Ory Kratos instead of hand-rolled auth API
honeyDue identity is now owned by Ory Kratos (auth.myhoneydue.com). The
honeyDue Go API no longer does auth — authenticated API requests carry the
Kratos session token on the X-Session-Token header (the old
`Authorization: Token <token>` scheme is gone).
What changed:
- models/Kratos.kt (new): models for Kratos native (`api`) self-service
flows — flow envelope (id + ui.action + ui.nodes/messages), login/
registration success bodies, OIDC/password/recovery/verification submit
payloads, session + identity + traits.
- ApiConfig.kt / ApiClient.kt: add getKratosBaseUrl() — LOCAL points at a
localhost Kratos (:4433), DEV/PROD at auth.myhoneydue.com. Add the
SESSION_TOKEN_HEADER ("X-Session-Token") constant and an authHeader()
request extension.
- AuthApi.kt: rewritten to drive Kratos native flows —
login (GET .../self-service/login/api -> POST ui.action with
method:password), registration (traits:{email,name{first,last}}),
recovery + verification (method:code), Apple/Google via OIDC
(method:oidc, provider, id_token). Kratos validation errors are pulled
from ui.nodes[].messages / ui.messages. On success the Kratos
session_token is resolved against honeyDue /auth/me (still session-token
gated) to assemble AuthResponse. Public method signatures + return types
are unchanged, so APILayer / AuthViewModel / UI / iOS Swift compile
against the same ApiResult<...> shapes with no rework.
- ApiClient.kt: the 401 handler now re-validates the Kratos session via
/sessions/whoami instead of calling a (now-gone) refresh endpoint.
TokenExpiredException is kept (messages updated).
- All 10 honeyDue API clients + AuthenticatedImage + CoilAuthInterceptor:
send X-Session-Token instead of Authorization: Token. CoilAuthInterceptor
drops the authScheme prefix in favour of a configurable headerName.
- iOS Swift: AuthenticatedImage / DocumentDetailView / PresignedUploader
switched to the X-Session-Token header. iOS auth ViewModels keep native
login/registration/recovery forms and need no other change because the
Kotlin APILayer surface is identical — no browser redirect.
- Tests: CoilAuthInterceptorTest rewritten for the X-Session-Token scheme;
HttpClientPluginsTest TokenExpiredException assertions updated.
Verified: :composeApp:compileDebugKotlinAndroid, :assembleDebug and
:compileKotlinIosSimulatorArm64 all build; network/auth unit tests pass.
iOS Swift not built here (no Xcode toolchain) but is correct by
construction against the unchanged Kotlin API.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -314,9 +314,10 @@ class MainActivity : FragmentActivity(), SingletonImageLoader.Factory {
|
||||
return ImageLoader.Builder(context)
|
||||
.components {
|
||||
// Auth interceptor runs before the network fetcher so every
|
||||
// image request carries the current Authorization header, with
|
||||
// 401 -> refresh-token -> retry handled transparently. Mirrors
|
||||
// iOS AuthenticatedImage.swift (Stream U).
|
||||
// image request carries the current X-Session-Token header
|
||||
// (Kratos session token), with 401 -> session re-check ->
|
||||
// retry handled transparently. Mirrors iOS
|
||||
// AuthenticatedImage.swift.
|
||||
add(
|
||||
CoilAuthInterceptor(
|
||||
tokenProvider = { TokenStorage.getToken() },
|
||||
@@ -324,7 +325,6 @@ class MainActivity : FragmentActivity(), SingletonImageLoader.Factory {
|
||||
val r = APILayer.refreshToken()
|
||||
if (r is ApiResult.Success) r.data else null
|
||||
},
|
||||
authScheme = "Token",
|
||||
)
|
||||
)
|
||||
add(KtorNetworkFetcherFactory())
|
||||
|
||||
Reference in New Issue
Block a user