Hey! Long question incoming, as I've spent a bit too many hours now trying to set up a custom UI and need some help figuring out what's going on. So from my understanding in the doc and based on the typescript project you have to set up a backend that proxies some of the API requests to Zitadel since the API requires a Bearer token. The browser doesn't have a token prior to this and all the API endpoints require a token, including the session and user endpoints. So my idea was then to set up the following stack: - Static Nuxt/Vue FE which is configured with a web application in Zitadel and a PKCE. - Rust API backend with a SA that is allowed to start a new login session. The FE (aka. browser) would then communicate with the backend to authenticate to a Zitadel application. The backend would use the SA to get extra permissions and would be responsible to communicate with Zitadel to create, update and finalize sessions which eventually would result in the browser getting an OIDC JWT token that it can use to communicate directly with the Zitadel API and other API's, the Rust API would handle the sessions and keep the sensitive information away from the client-side javascript through a secure cookie and mimick the functionality that the Zitadel console does today and enforce a login flow that adds extra metadata and enforces a specific flow. Somehow, I also hoped that there's a way that the FE could have the Zitadel instance set a secure cookie or a token that the Rust API gives it, so it can directly access the Zitadel API without having to go through the Rust API. Based on assumptions, as I can't find documentation on how to set up an SA for custom login UI, to get this to work you have to: 1. Create an SA on the Tenant 2. Grant the SA the Zitadel IAM_OWNER role. 3. Authenticate the SA either through client secret or by using a preauthenticated SA JWT key. 4. If SA is authenticated, then the scope to allow API access has to be added. To begin a login process the documentation says "it always starts with an AuthRequest", to do this you can first create an AuthRequest by doing a POST to `{zitadelinstance}/oauth/v2/authorize` to fetch some extra information, this can be achieved through a proxy request which sends the request from the browser->backend proxy->Zitadel. To make sure that Zitadel doesn't redirect the user to the Zitadel UI on the first authroize request, you have to toggle the `Use new Login UI` and set the `Custom base URL for the new Login UI` to the backend proxy, when the backend proxy gets the information, the backend can call the Zitadel API again at `{zitadelinstance}/v2/oidc/auth_requests/:authRequestID` to get extra information about the user and it can then redirect the browser back to the login UI and attach a `authRequestID` to the query of the FE, this way the browser later can use the authRequestID to finalize the session through `{zitadelinstance}/v2/oidc/auth_requests/:authRequestId`. Afterward you've created the AuthRequest, you can create a session by doing a POST to `/v2/sessions`. According to the documentation, normally to create a session, you need to do: ```json "checks": { "user": { "loginName": "minni-mouse@mouse.com" } } ``` And this works, a sessionToken is returned. However according to the PassKey doc, you need to "When creating the new session make sure to include the challenge for passkey, resp. webAuthN with a required user verification and the domain of your login UI." - this is where it fails. If I add a user that has Passkeys configured and pass data according to the doc: ```json { "checks": { "user": { "loginName": "minni-mouse@mouse.com" } }, "metadata": {}, "challenges": { "webAuthN": { "domain": "example.domain.com", "userVerificationRequirement": "USER_VERIFICATION_REQUIREMENT_REQUIRED" } } } ``` I simply get this wonderful error: ```json 500 Internal Server Error: {"code":13, "message":"WebAuthN begin login failed (WEBAU-4G8sw)", "details":[{"@type":"type.googleapis.com/zitadel.v1.ErrorDetail", "id":"WEBAU-4G8sw", "message":"WebAuthN begin login failed"}]}` ``` I haven't gotten around to testing the password authentication with the session API, but if I remember correctly, I weren't able to patch the session to get the publicKeyCredential and got a similar Internal Server error. The logs on Zitadel doesn't give any more clues to what's going on, other than not finding the clientId of the SA account, the logs says this might be because it's a SA. I've tried checking the error code to see where it is generated in the codebase, but from what I remember, it didn't give me any better clues on how to troubleshoot the issue. I assume the WebAuthN challenge might need to be done through a subsequent PATCH to the session, but this is contradictory to the docs and the whole thing seems like a bug to me at this moment. If the 500 HTTP status code is used correctly, it's a Zitadel issue, but it seems weird that PassKeys works in Zitadel and that the typescript project mentions PassKeys being complete (though it also says it's not done in a different doc). Also the documentation misssed the critical information on what permissions, roles and how to set up the SA for a custom UI and what user/SA/app that has to be used for the bearer token for the session requests. It's simply incomplete and the Typescript project both uses Next.js server functions and web-grpc so it's difficult to use it as a reference to understand the setup since it' so tightly coupled and doesn't follow separation of concerns. I tried mimicking the Next.js app in case if it's a bug in the REST code in Zitadel but I couldn't get all the GRPC functions to work with the Zitadel APIs. I assume this might be due to the Rust GRPC crate being from January and Zitadel is now at v3.3.0. I've tried getting my setup to work on `zitadel:v3.2.3`. Anyone got a clue on how to get this to work or if it's a but that needs to be fixed?? Thanks!