traefik-forward-auth icon indicating copy to clipboard operation
traefik-forward-auth copied to clipboard

Unable to Integrate With Nextcloud as Oauth2 Provider

Open joeyame opened this issue 3 years ago • 3 comments

Hello there,

I am currently on DAY 3 of trying to get my new server/networking setup working, and am very close to flat out losing it. Hopefully someone can help get this setup working!

Over the past week I've been migrating from a server dedicated to running Nextcloud (as a stand-alone web application) to a more containerized and extensible format. I've already gotten Nextcloud into a container and it looks as though everything is good on that end. I also opted to set up Traefik so I can constantly run various services and bring them up or down at will. This is working great!

One of the reasons I'm fiddling about with forward-auth is that I want to run a variety of services on my domain that do not support passwords themselves, like code-server. But at the same time I thought a more SSO approach would be nice. So after wasting 2 days trying to get Authelia to work as a SSO for Nextcloud and others, I decided that it would be okay if I could use the Nextcloud login as the SSO for services outside of nextcloud.

I've seen various posts about people who got this to work, so I know it's possible:

  • https://help.nextcloud.com/t/nextcloud-as-oauth2-provider-for-any-traefik-forward-auth-possible/93565
  • https://github.com/thomseddon/traefik-forward-auth/issues/189

I am unable to achieve a usable result though, not even considering decoding the user json. For my services that header doesn't matter, I just need to make sure randos can't access certain services because they are blocked by a nextcloud login.

I should note that I got this flow working with the Google Oauth services, and did not change the setup much to switch to Nextcloud. Here are the relevant files

/server/traefik/docker-compose:

version: "3.5"

services:
        traefik:
                image: "traefik:v2.6"
                container_name: "traefik"
                command:
                        - "--api.insecure=true"
                        - "--providers.docker=true"
                        - "--providers.docker.exposedbydefault=false"
                        - "--providers.file.directory=/etc/traefik/dynamic_conf"
                        - "--entrypoints.web.address=:80"
                        - "--entrypoints.websecure.address=:443"
                ports:
                        - "80:80"
                        - "443:443"
                        - "8080:8080"
                volumes:
                        - "/var/run/docker.sock:/var/run/docker.sock:ro"
                        - "./certs:/tools/certs"
                        - "./conf.yml:/etc/traefik/dynamic_conf/conf.yml:ro"
                networks:
                        - "traefik"
                restart: "unless-stopped"

        whoami:
                image: containous/whoami
                labels:
                        - "traefik.enable=true"
                        - "traefik.http.routers.whoami.rule=Host(`who.domain.com`)"
                        - "traefik.http.routers.whoami.entrypoints=web,websecure"
                        - 'traefik.http.routers.whoami.tls=true'
                        - "traefik.http.routers.whoami.middlewares=traefik-forward-auth"
                networks:
                        - "traefik"

networks:
        traefik:
                external: true

/server/nextcloud/docker-compose:

version: "3"

services:
        nextcloud:
                image: nextcloud:latest
                restart: unless-stopped
                environment:
                        - MYSQL_HOST=mysql
                        - MYSQL_DATABASE=nextcloud
                        - MYSQL_USER=nextcloud
                        - MYSQL_PASSWORD=<pass>
                volumes:
                        - ./html:/var/www/html
                labels:
                        - "traefik.enable=true"
                        - "traefik.http.routers.nextcloud.rule=Host(`cloud.domain.com`)"
                        - "traefik.http.routers.nextcloud.entrypoints=websecure"
                        - "traefik.http.routers.nextcloud.tls=true"
                networks:
                        - "traefik"

        mysql:
                image: mysql:8.0
                restart: unless-stopped
                environment:
                        - MYSQL_DATABASE=nextcloud
                        - MYSQL_USER=nextcloud
                        - MYSQL_PASSWORD=<pass>
                        - MYSQL_ROOT_PASSWORD=<pass>
                volumes:
                        - ./mysql:/var/lib/mysql
                networks:
                        - "traefik"

        traefik-forward-auth:
                image: thomseddon/traefik-forward-auth
                restart: unless-stopped
                environment:
                        - LOG_LEVEL=panic
                        - LOG_FORMAT=text
                        - COOKIE_DOMAIN=domain.com
                        - DEFAULT_PROVIDER=generic-oauth
                        - PROVIDERS_GENERIC_OAUTH_AUTH_URL=https://cloud.domain.com/index.php/apps/oauth2/authorize
                        - PROVIDERS_GENERIC_OAUTH_TOKEN_URL=https://cloud.domain.com/index.php/apps/oauth2/api/v1/token
                        - PROVIDERS_GENERIC_OAUTH_USER_URL=https://cloud.domain.com/index.php/ocs/v2.php/cloud/user?format=json
                        - PROVIDERS_GENERIC_OAUTH_CLIENT_ID=<nextcloud client id>
                        - PROVIDERS_GENERIC_OAUTH_CLIENT_SECRET=<nextcloud client secret>
                        - SECRET=randomthing
                        - INSECURE_COOKIE=false
                labels:
                        - "traefik.enable=true"
                        - "traefik.http.middlewares.traefik-forward-auth.forwardauth.address=http://traefik-forward-auth:4181"
                        - "traefik.http.middlewares.traefik-forward-auth.forwardauth.authResponseHeaders=X-Forwarded-User"
                        - "traefik.http.services.traefik-forward-auth.loadbalancer.server.port=4181"
                networks:
                        - "traefik"
networks:
        traefik:
                external: true

Expected behavior:

  1. Go to who.domain.com
  2. Redirected to nextcloud to grant access
  3. Redirected back to who.domain.com and access page

Actual behavior:

  1. Go to who.domain.com
  2. Redirected to nextcloud to grant access
  3. Redirected to the following url: https://who.domain.com/_oauth?state=7126511%3Ageneric-oauth%3Ahttps%3A%2F%2Fwho.domain.com%2F&code=0VVa3RwbTkyFfQx (numbers shortened)
  4. this page does not redirect to who.domain.com, but shows "Service unavailable" in the html.
  5. Using the networking tool, I was able to find this failed request (copied as curl)
curl 'https://who.domain.com/_oauth?state=fa47e5bd62fdc%3Ageneric-oauth%3Ahttps%3A%2F%2Fwho.domain.com%2F&code=0bXLndV9DBTzr' \
  -H 'authority: who.domain.com' \
  -H 'cache-control: max-age=0' \
  -H 'upgrade-insecure-requests: 1' \
  -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36' \
  -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' \
  -H 'sec-gpc: 1' \
  -H 'sec-fetch-site: same-site' \
  -H 'sec-fetch-mode: navigate' \
  -H 'sec-fetch-user: ?1' \
  -H 'sec-fetch-dest: document' \
  -H 'accept-language: en-US,en;q=0.9' \
  -H 'cookie: _forward_auth_csrf_0ca605=0ca6054140b4f192abf7d227bb58cc77; _forward_auth_csrf_fa47e5=fa47e5bd630f3ea10a6cb62dc15a2fdc' \
  --compressed

It gets the following response: image

joeyame avatar Mar 12 '22 16:03 joeyame

I have no idea where things are going wrong - if it's this proxy, if it's nextcloud, or even if it's something else. The behavior is repeatable in various browsers. Any help anyone can offer will be greatly appreciated, because I am well beyond wit's end.

joeyame avatar Mar 12 '22 16:03 joeyame

There are two ways of setting this up (that I know of).

Edit: Since you have the forwardAuth set on the whoami service, this should not be needed at all. I needed this for a different deployment. Setting log level to DEBUG should help you understand why it failed. Always try in incognito to make sure.

First is that you direct all traffic on all domains with the path of /_oauth to the traefik-forward-auth container using the below labels. Then, the forward-auth generates dynamic redirect URIs as usual, which you need to add as valid redirect on your IdP (Nextcloud) and you are good to go. You do not have anything routing traffic to the traefik-forward-auth container. (Edit: We have the forwardAuth middleware doing this)

                   labels:
                        - "traefik.http.routers.fwd-auth.rule=PathPrefix(`/_oauth`)"
                        - "traefik.http.routers.fwd-auth.entrypoints=websecure"
                        - "traefik.http.routers.fwd-auth.tls=true"

Now, when the redirect happens, instead of getting a 503 from the whoami container (I am assuming), you should get redirected successfully.

The second is that you set this up in auth-host mode, where all the redirects happen to a single host, let's say sso.domain.com. You can add the below labels to achieve that, and you need to configure as shown https://github.com/thomseddon/traefik-forward-auth#auth-host-mode.

                   environment:
                        - AUTH_HOST=sso.domain.com
                   labels:
                        - "traefik.http.routers.fwd-auth.rule=Host(`sso.domain.com`)"
                        - "traefik.http.routers.fwd-auth.entrypoints=websecure"
                        - "traefik.http.routers.fwd-auth.tls=true"

Either way, set LOG_LEVEL=debug so that you can see if any error actually occurs on the traefik-forward-auth.

adyanth avatar Mar 19 '22 06:03 adyanth

Also, Authelia is good, I've used it before. The problem is that Nextcloud does not do well with OAuth sign in. The only way I was able to get it to work is with SAML and Keycloak.

That is another recommendation, it can be a pain to set up once, but once up, it is a solid choice. I have had no issues, and all the services, even the cloud services I host/use integrate with Keycloak which in turn connects to Github/Google/Microsoft for easy login and Duo for 2FA. It also supports SAML for the weird outliers like Nextcloud.

adyanth avatar Mar 19 '22 06:03 adyanth