microsoft / DurableFunctionsMonitor

A monitoring/debugging UI tool for Azure Durable Functions

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Client-directed login flow stuck in loop on K8s

rsirny opened this issue · comments

commented

I am trying to deploy DFM to AKS using the latest scaletone/durablefunctionsmonitor:6.2 image. The instance should be using client-directed login flow. The set up is done via WEBSITE_AUTH_CLIENT_ID, WEBSITE_AUTH_OPENID_ISSUER and DFM_ALLOWED_APP_ROLES.

Unfortunately, the authentication does not work (locally in Docker Desktop as well as in AKS). I am redirected to AAD login screen, provide my credentials and then there is redirection back to my instance. After this initial login, the UI keeps flashing with message Login in process and after a while it redirects to login.microsoft.com with message We couldn't sign you in. Please try again..

The relevant message from browser logs seems to be:

Navigated to https://dfm.kubernetes.docker.internal/
main.fd39a094.js:sourcemap:2 DFM: acquireTokenSilent() failed (ClientAuthError: User login is required. For silent calls, request must contain either sid or login_hint), so calling acquireTokenRedirect()...
main.fd39a094.js:sourcemap:2 Failed to handle login redirect. name: ClientAuthError, message: User login is required. For silent calls, request must contain either sid or login_hint, errorCode: user_login_error, errorMessage: User login is required. For silent calls, request must contain either sid or login_hint, accountState: REDACTED
Navigated to https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/authorize?response_type=id_token&scope=openid%20profile&client_id=CLIENT_ID&redirect_uri=https%3A%2F%2Fdfm.kubernetes.docker.internal&state=REDACTED&nonce=REDACTED&client_info=1&x-client-SKU=MSAL.JS&x-client-Ver=1.4.17&client-request-id=REDACTED&response_mode=fragment

The errors originate from LoginState.ts:140 and LoginState.ts:195.

I have also tried using DFM_ALLOWED_USER_NAMES, but the result is the same. The same error occurs when DFM K8s ingress is using prefix instead of host. Redacted manifest for my Azure AD app is here azure-ad-redacted-manifest.zip.

Docker Desktop K8s cluster repro steps:

  • install nginx ingress helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --namespace ingress-nginx --create-namespace --set controller.setAsDefaultIngress=true
  • install azurite via kubectl apply -f ./azurite.yaml (azurite.yaml provided in azurite.zip
  • setup your Azure AD app according to the official guide with redirect URI set to https://dfm.kubernetes.docker.internal and create app role dfm-full-access
  • edit WEBSITE_AUTH* variables of dfm secret in dfm.yaml (dfm.zip) and install dfm via kubectl apply -f ./dfm.yaml
  • add 127.0.0.1 dfm.kubernetes.docker.internal to your hosts file
  • go to https://dfm.kubernetes.docker.internal

Hi @rsirny , first of all, can you please confirm that you've configured your AAD app for client-directed login flow as described here?
Most important settings to pay attention to are Redirect URI (must be your DfMon's URI without any extra path) and ID tokens enabled.

commented

Thanks for that, @rsirny . I can see from your manifest, that DfMon is hosted under dfm route prefix (if I read it correctly).
Can you please confirm that you've configured DFM_INGRESS_ROUTE_PREFIX setting accordingly, as described here ?

commented

The dfm route prefix is a leftover from my attempts to make it work after using the host failed. I did use the DFM_INGRESS... in that case, but the app behaved the same way.

The app manifest has also https://dfm.kubernetes.docker.internal reply url which is what I used for ingress in the repro sample:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: dfm-int
  labels:
    helm.sh/chart: dfm-0.1.0
    app.kubernetes.io/name: dfm
    app.kubernetes.io/instance: dfm
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: dfm.kubernetes.docker.internal
    http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: dfm
              port:
                number: 80
  tls:
  - hosts:
    - dfm.kubernetes.docker.internal

If I disable the authentication via DFM_NONCE, everything is working fine so the networking should be set up correctly.

commented

Here is a screenshot of what is happening after I login via Microsoft login screen.
Screenshot 2023-04-20 084257
And this is how it ends up:
Screenshot 2023-04-20 084446

Screenshot 2023-04-20 085744

Thanks for all those details and for reporting this, @rsirny !

I confirm that I was able to repro the issue.
Looks like it was caused by me recently bumping up msal.js library from 1.4.12 to 1.4.17. This recent version seems to have some kind of regression in it, which results in auth failures on the client side.

Haven't discovered yet what the issue there actually is, so just reverted msal.js back to 1.4.12 and re-pushed container images under the same tag - 6.2.

Should work now. Please, check.

commented

The login loop is gone, thanks for swift fix :)

I have run into two more issues, but I will fill them separately for better traceability.

PS: I was able to start using role-based membership only after debugging the solution locally and figuring out that roles from my token are mapped to http://schemas.microsoft.com/ws/2008/06/identity/claims/role claim type. Another token claim <-> principal claim possible mapping I know of is that it becomes role. I am not sure what determines the mapping, but it might be worth mentioning these values in the docs as not everybody will be capable of debugging the backend locally :)