Nix custom build auth callback path returning 404

I’m building nix packages for corteza and ui but I’ve hit an issue with the path /auth/callback returning a 404 when I attempt login with Google.

The following sequence happens:

GET https://XXX/auth/external/google < 307
GET https://accounts.google.com/o/oauth2/auth?client_id=XXX&redirect_uri=https%3A%2F%2FXXX%2Fauth%2Fexternal%2Fgoogle%2Fcallback&response_type=code&scope=email&state=XXX < 302
GET https://XXX/auth/external/google/callback?state=XXX&code=XXX&scope=email+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&hd=XXX&prompt=none < 303
GET https://XXX/auth/oauth2/authorize-client < 303
GET https://XXX/auth/oauth2/authorize < 302
GET https://XXX/auth/callback?code=XXX&state=XXX < 404

It works fine if I use the docker image so I think I might have missed copying some files?

The 404 is still seen even without AUTH_DEVELOPMENT_MODE=true or AUTH_ASSETS_PATH set.

In case anyone finds this useful here are my nix files:


default.nix:

{ lib
, stdenv
, callPackage
, buildGoModule
, fetchFromGitHub
, fetchurl
}:
let
  version = "2021.3.11";
  server = callPackage ./server.nix { inherit version; };
  corteza-webapp-admin = fetchurl {
    url = "https://releases.cortezaproject.org/files/corteza-webapp-admin-${version}.tar.gz";
    sha256 = "1in3nvh9skh64l4ba21vxlgvql1px7pf3ycm7sjr7a3vm26apwns"; # 2021.3.11
  };
  corteza-webapp-compose = fetchurl {
    url = "https://releases.cortezaproject.org/files/corteza-webapp-compose-${version}.tar.gz";
    sha256 = "1kfjqlv1imy1kpfs66qy3xlrrm5ibk7fpirjxgs74fh97n7gkf9w"; # 2021.3.11
  };
  corteza-webapp-workflow = fetchurl {
    url = "https://releases.cortezaproject.org/files/corteza-webapp-workflow-${version}.tar.gz";
    sha256 = "08pzd9ymx8yq8bjyhh154jwfrxybxybba0cq5kp0jsnm28bizxx6"; # 2021.3.11
  };
  corteza-webapp-one = fetchurl {
    url = "https://releases.cortezaproject.org/files/corteza-webapp-one-${version}.tar.gz";
    sha256 = "0354zshmdqxngaqg0lqzpcpk0l86m24asc5lsinard25bs9zlm4j"; # 2021.3.11
  };
in
stdenv.mkDerivation rec {
  pname = "corteza";
  inherit version;
  src = ./.;
  installPhase = ''
    mkdir -p $out
    cp -r ${server}/* $out
    mkdir -p $out/webapp/public/admin
    mkdir -p $out/webapp/public/compose
    mkdir -p $out/webapp/public/workflow
    tar -xzmokf ${corteza-webapp-one} --directory=$out/webapp/public
    tar -xzmokf ${corteza-webapp-admin} --directory=$out/webapp/public/admin
    tar -xzmokf ${corteza-webapp-compose} --directory=$out/webapp/public/compose
    tar -xzmokf ${corteza-webapp-workflow} --directory=$out/webapp/public/workflow
  '';
}

server.nix:

{ lib
, buildGoModule
, fetchFromGitHub
, version
}:
buildGoModule rec {
  pname = "corteza";
  inherit version;
  src = fetchFromGitHub {
    owner = "cortezaproject";
    repo = "corteza-server";
    rev = "${version}";
    sha256 = "1ni9wvpdxn7j12c2n593szls1bv0sgj47aglxsrz1bvf8p3a30rr";
  };
  vendorSha256 = null;
  subPackages = [ "cmd/corteza" ];
  postInstall = ''
    cp -r provision $out
    cp -r auth/assets $out/auth
  '';
  doCheck = false;
  meta = with lib; {
    description = "Corteza is the only 100% free, open-source, standardized and enterprise-grade Low-code platform";
    homepage = "https://cortezaproject.org/";
    license = licenses.asl20;
    # maintainers = [ maintainers. ];
  };
}

config-snippet.nix:

      corteza = rec {
        package = local.pkgs.corteza;
        host = "corteza${instance}";
        domain = local.secrets.domain;
        port = local.ports.corteza;
        fqdn = "${host}.${domain}";
        version = "2021.3";
        imageHost = "cortezaproject/corteza-server";
        image = "${imageHost}:${version}";
        listenAddress = "127.0.0.1:${toString port}";
        authBaseURL = "https://${fqdn}/auth";
        externalCallbackURL = "${authBaseURL}/external/{provider}/callback";
        db = local.secrets.corteza.db // {
          dsn = (c: "${c.username}:${c.password}@tcp(${c.host}:${toString c.port})/${c.database}?collation=utf8mb4_general_ci") local.secrets.corteza.db;
        };
        env = {
          "DB_DSN" = db.dsn;
          "DOMAIN" = fqdn;
          "VERSION" = version;
          "HTTP_ADDR" = listenAddress;
          "AUTH_BASE_URL" = authBaseURL;
          "AUTH_EXTERNAL_REDIRECT_URL" = externalCallbackURL;
          "HTTP_WEBAPP_ENABLED" = "true";
          "HTTP_LOG_REQUEST" = "true";
          "HTTP_LOG_RESPONSE" = "true";
          "HTTP_ENABLE_DEBUG_ROUTE" = "true";
          "ACTIONLOG_DEBUG" = "true";
          "CORREDOR_DEBUG" = "true";
          "CORREDOR_LOG_ENABLED" = "true";
          "GRPC_CLIENT_LOG" = "true";
          "DB_LOGGER" = "true";
          "HTTP_ERROR_TRACING" = "true";
          "HTTP_METRICS" = "true";
          "AUTH_DEVELOPMENT_MODE" = "true";
          "AUTH_ASSETS_PATH" = "${package}/auth";
          "UPGRADE_DEBUG" = "true";
        };
      };

Just in case, here is the auth.* settings from the db:

name value
auth.external.enabled true
auth.mail.from-address “info@example.tld”
auth.mail.from-name “Example Sender”
auth.internal.enabled false
auth.internal.signup.enabled false
auth.internal.signup.email-confirmation-required false
auth.internal.password-reset.enabled false
auth.external.providers.google.key “”
auth.external.providers.google.secret “”
auth.external.providers.google.enabled true
auth.external.providers.facebook.key “”
auth.external.providers.facebook.secret “”
auth.external.providers.facebook.enabled false
auth.external.providers.github.key “”
auth.external.providers.github.secret “”
auth.external.providers.github.enabled false
auth.external.providers.linkedin.key “”
auth.external.providers.linkedin.secret “”
auth.external.providers.linkedin.enabled false

I think I have resolved this. I moved the webapp/public content to the webapp directory and set "HTTP_WEBAPP_BASE_DIR" = "${package}/webapp"; in the environment.

I think it was because I didn’t set the working directory to the package directory which meant the default value for HTTP_WEBAPP_BASE_DIR (webapp/public) was not finding apps, only auth. Hopefully someone finds this helpful.

I’m working on a nixos module too but there is a fair bit to do as I’m planning on using caddy for tls, load balancing and static content, minio for files (and potential gateway to google bucket), and mysql. I’ve got a nixops deployment working for a single server. If anyone is interested in my nix related work let me know here.


Here’s my working nix package:

{ lib
, stdenv
, buildGoModule
, fetchFromGitHub
, fetchurl
}:
let
  meta = with lib; {
    description = "Corteza is the only 100% free, open-source, standardized and enterprise-grade Low-code platform";
    homepage = "https://cortezaproject.org/";
    license = licenses.asl20;
    # maintainers = [ maintainers. ];
  };
  version = "2021.3.11";
  server = buildGoModule rec {
    pname = "corteza-server";
    inherit version meta;
    src = fetchFromGitHub {
      owner = "cortezaproject";
      repo = pname;
      rev = "${version}";
      sha256 = "1ni9wvpdxn7j12c2n593szls1bv0sgj47aglxsrz1bvf8p3a30rr";
    };
    vendorSha256 = null;
    subPackages = [ "cmd/corteza" ];
    postInstall = ''
      cp -r provision $out
      rm -f $out/provision/README.adoc $out/provision/update.sh
      cp -r auth/assets $out/auth
    '';
    doCheck = false;
  };
  releasesURL = "https://releases.cortezaproject.org/files";
  webapp = app: "${releasesURL}/corteza-webapp-${app}-${version}.tar.gz";
  admin = fetchurl { url = webapp "admin"; sha256 = "1in3nvh9skh64l4ba21vxlgvql1px7pf3ycm7sjr7a3vm26apwns"; };
  compose = fetchurl { url = webapp "compose"; sha256 = "1kfjqlv1imy1kpfs66qy3xlrrm5ibk7fpirjxgs74fh97n7gkf9w"; };
  workflow = fetchurl { url = webapp "workflow"; sha256 = "08pzd9ymx8yq8bjyhh154jwfrxybxybba0cq5kp0jsnm28bizxx6"; };
  one = fetchurl { url = webapp "one"; sha256 = "0354zshmdqxngaqg0lqzpcpk0l86m24asc5lsinard25bs9zlm4j"; };
in
stdenv.mkDerivation rec {
  pname = "corteza";
  inherit version meta;
  src = ./.;
  installPhase = ''
    mkdir -p $out/webapp/admin $out/webapp/compose $out/webapp/workflow
    cp -r ${server}/* $out
    tar -xzmokf ${one} --directory=$out/webapp
    tar -xzmokf ${admin} --directory=$out/webapp/admin
    tar -xzmokf ${compose} --directory=$out/webapp/compose
    tar -xzmokf ${workflow} --directory=$out/webapp/workflow
  '';
}

Thank you for posting a working solution; I’m sure someone will benefit from this!
Would you mind if we use this post as a base if we decide to incorporate this into the documentation?

I don’t mind if you use this for any purpose.

I’ve found something odd with my custom build not automatically creating the default oauth client on first installation. It worked at one point then didn’t. I’ve gone back to the docker image instead of my build for now.

It could be that I’m calling provision and migrate from the cli before running the api which might prevent the first run things from happening correctly. I’m doing this because I set some auth configuration so oauth2 sign on is the only option. I might have to use a modified copy of the provisioning yaml files and let the serve-api do the standard provisioning and migration with my yamls instead of running the cli as a pre-start script.

When I figure out what I missed, I’ll post here.

I got it to work. I was not running from a directory with the provisioning files so when starting, it didn’t create oauth clients or anything else.

I’m still refining the nix expressions but will share if anyone is interested.