Viktor is adding the Android APK (Capacitor Shell) for TripIt. The Shell cannot use the browser's forward-auth cookie dance, so per tripit ADR-0017 it logs in with OIDC Code+PKCE and calls the API with bearer JWTs: - authentik.tf: tripit-app OAuth2 provider (public client + PKCE — an APK holds no secret), custom-scheme redirect me.viktorbarzin.tripit://callback, RS256, 1h access / 90d refresh (offline_access mapping attached so refresh tokens are issued), plus the TripIt App application. - main.tf: new ingress host tripit-api.viktorbarzin.me -> same tripit Service, no forward-auth (backend validates the JWTs itself once tripit AUTH_MODE=hybrid lands — slice 2), inbound X-authentik-* deleted via the existing traefik strip-auth-headers middleware so the header fallback can never be spoofed through this host. Closes nothing here; tracked as viktor/tripit#49. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
84 lines
2.9 KiB
HCL
84 lines
2.9 KiB
HCL
# Authentik OAuth2 provider for the TripIt App (the native Android Shell) —
|
|
# tripit ADR-0017, viktor/tripit#49. The Shell does an Authorization Code +
|
|
# PKCE login in the system browser and lands back in the app via the
|
|
# custom-scheme redirect; the backend validates the issued RS256 JWTs itself
|
|
# (AUTH_MODE=hybrid, tripit slice 2). client_type "public": an APK cannot keep
|
|
# a client secret, PKCE is the binding. The bearer-only ingress host this
|
|
# pairs with is module.ingress_api in main.tf.
|
|
|
|
data "vault_kv_secret_v2" "authentik_tf" {
|
|
mount = "secret"
|
|
name = "authentik"
|
|
}
|
|
|
|
provider "authentik" {
|
|
url = "https://authentik.viktorbarzin.me"
|
|
token = data.vault_kv_secret_v2.authentik_tf.data["tf_api_token"]
|
|
}
|
|
|
|
data "authentik_flow" "default_authorization_implicit_consent" {
|
|
slug = "default-provider-authorization-implicit-consent"
|
|
}
|
|
|
|
data "authentik_flow" "default_provider_invalidation" {
|
|
slug = "default-provider-invalidation-flow"
|
|
}
|
|
|
|
data "authentik_certificate_key_pair" "signing" {
|
|
name = "authentik Self-signed Certificate"
|
|
}
|
|
|
|
data "authentik_property_mapping_provider_scope" "openid" {
|
|
managed = "goauthentik.io/providers/oauth2/scope-openid"
|
|
}
|
|
|
|
data "authentik_property_mapping_provider_scope" "profile" {
|
|
managed = "goauthentik.io/providers/oauth2/scope-profile"
|
|
}
|
|
|
|
data "authentik_property_mapping_provider_scope" "email" {
|
|
managed = "goauthentik.io/providers/oauth2/scope-email"
|
|
}
|
|
|
|
# offline_access is what makes Authentik issue a refresh token — the Shell
|
|
# stores only that and re-derives short-lived access tokens. Looked up by
|
|
# scope_name (the managed identifier is version-dependent).
|
|
data "authentik_property_mapping_provider_scope" "offline_access" {
|
|
scope_name = "offline_access"
|
|
}
|
|
|
|
resource "authentik_provider_oauth2" "tripit_app" {
|
|
name = "tripit-app"
|
|
client_id = "tripit-app"
|
|
client_type = "public"
|
|
|
|
authorization_flow = data.authentik_flow.default_authorization_implicit_consent.id
|
|
invalidation_flow = data.authentik_flow.default_provider_invalidation.id
|
|
|
|
allowed_redirect_uris = [
|
|
{
|
|
matching_mode = "strict"
|
|
url = "me.viktorbarzin.tripit://callback"
|
|
},
|
|
]
|
|
|
|
access_token_validity = "hours=1"
|
|
refresh_token_validity = "days=90"
|
|
include_claims_in_id_token = true
|
|
signing_key = data.authentik_certificate_key_pair.signing.id
|
|
|
|
property_mappings = [
|
|
data.authentik_property_mapping_provider_scope.openid.id,
|
|
data.authentik_property_mapping_provider_scope.profile.id,
|
|
data.authentik_property_mapping_provider_scope.email.id,
|
|
data.authentik_property_mapping_provider_scope.offline_access.id,
|
|
]
|
|
}
|
|
|
|
resource "authentik_application" "tripit_app" {
|
|
name = "TripIt App"
|
|
slug = "tripit-app"
|
|
protocol_provider = authentik_provider_oauth2.tripit_app.id
|
|
meta_launch_url = "https://tripit.viktorbarzin.me"
|
|
policy_engine_mode = "any"
|
|
}
|