Repository: jupyterhub/jupyterhub

Issue:
PAMAuthenticator / LocalAuthenticator not checking primary group when using allowed_groups
<!-- Thank you for contributing. These HTML comments will not render in the issue, but you can delete them once you've read them if you prefer! -->

### Bug description

When trying to use PAMAuthenticator or LocalAuthenticator with the c.PAMAuthenticator.allowed_groups configuration parameter I wasn't able to log in even though users were in the set group and the correct password was entered. The error message in the logs was just a vague "User 'XY' not allowed.". Turns out the Authenticators seem to only check secondary groups.

<!-- Use this section to clearly and concisely describe the bug. -->

### How to reproduce

<!-- Use this section to describe the steps that a user would take to experience this bug. -->

1. Set `c.PAMAuthenticator.allowed_groups = {"jupyter"}` in jupyterhub_config.py
2. Create user using `useradd testuser -N -g jupyter`
3. Set password using passwd
4. Start Jupyterhub
5. Try to log in

#### Expected behaviour

<!-- Tell us what you thought would happen. -->
The user should be able to log in because he has the correct credentials and is member of the allowed group.
In my opinion the primary group of the user should also be checked or at least there should be a note in the documentation of the allowed_groups configuration parameter.

#### Actual behaviour

The user isn't able to log in and the log message is very vague with `[... JupyterHub auth:533] User 'testuser not allowed.`

<!-- Tell us what actually happens. -->

### Your personal set up

<!--
Tell us a little about the system you're using.
Please include information about how you installed,
e.g. are you using a distribution such as zero-to-jupyterhub or the-littlest-jupyterhub.
 -->

 - OS: 
    - 1. ubuntu 22.04 WSL on Win 11
    - 2. Docker quay.io/jupyterhub/jupyterhub:latest (4.0.2) on ubuntu 22.04. WSL on Win 11
 <!-- [e.g. ubuntu 20.04, macOS 11.0] -->
 - Version(s): 4.0.2
 <!-- e.g. jupyterhub --version, python --version --->

<details><summary>Full environment</summary>
<!-- For reproduction, it's useful to have the full environment. For example, the output of `pip freeze` or `conda list` --->

```
# packages in environment at /root/anaconda3:
#
# Name                    Version                   Build  Channel
_anaconda_depends         2023.09             py311_mkl_1
_libgcc_mutex             0.1                        main
_openmp_mutex             5.1                       1_gnu
abseil-cpp                20211102.0           hd4dd3e8_0
aiobotocore               2.5.0           py311h06a4308_0
aiofiles                  22.1.0          py311h06a4308_0
aiohttp                   3.8.5           py311h5eee18b_0
aioitertools              0.7.1              pyhd3eb1b0_0
aiosignal                 1.2.0              pyhd3eb1b0_0
aiosqlite                 0.18.0          py311h06a4308_0
alabaster                 0.7.12             pyhd3eb1b0_0
alembic                   1.13.0             pyhd8ed1ab_0    conda-forge
anaconda-anon-usage       0.4.2           py311hfc0e8ea_0
anaconda-catalogs         0.2.0           py311h06a4308_0
anaconda-client           1.12.1          py311h06a4308_0
anaconda-cloud-auth       0.1.3           py311h06a4308_0
anaconda-navigator        2.5.0           py311h06a4308_0
anaconda-project          0.11.1          py311h06a4308_0
anyio                     3.5.0           py311h06a4308_0
aom                       3.6.0                h6a678d5_0
appdirs                   1.4.4              pyhd3eb1b0_0
argon2-cffi               21.3.0             pyhd3eb1b0_0
argon2-cffi-bindings      21.2.0          py311h5eee18b_0
arrow                     1.2.3           py311h06a4308_1
arrow-cpp                 11.0.0               h374c478_2
astroid                   2.14.2          py311h06a4308_0
astropy                   5.1             py311hbed6279_0
asttokens                 2.0.5              pyhd3eb1b0_0
async-timeout             4.0.2           py311h06a4308_0
async_generator           1.10                       py_0    conda-forge
atomicwrites              1.4.0                      py_0
attrs                     22.1.0          py311h06a4308_0
automat                   20.2.0                     py_0
autopep8                  1.6.0              pyhd3eb1b0_1
aws-c-common              0.6.8                h5eee18b_1
aws-c-event-stream        0.1.6                h6a678d5_6
aws-checksums             0.1.11               h5eee18b_2
aws-sdk-cpp               1.8.185              h721c034_1
babel                     2.11.0          py311h06a4308_0
backcall                  0.2.0              pyhd3eb1b0_0
backports                 1.1                pyhd3eb1b0_0
backports.functools_lru_cache 1.6.4              pyhd3eb1b0_0
backports.tempfile        1.0                pyhd3eb1b0_1
backports.weakref         1.0.post1                  py_1
bcrypt                    3.2.0           py311h5eee18b_1
beautifulsoup4            4.12.2          py311h06a4308_0
binaryornot               0.4.4              pyhd3eb1b0_1
black                     23.3.0          py311h06a4308_0
blas                      1.0                         mkl
bleach                    4.1.0              pyhd3eb1b0_0
blinker                   1.7.0              pyhd8ed1ab_0    conda-forge
blosc                     1.21.3               h6a678d5_0
bokeh                     3.2.1           py311h92b7b1e_0
boltons                   23.0.0          py311h06a4308_0
boost-cpp                 1.73.0              h7f8727e_12
botocore                  1.29.76         py311h06a4308_0
bottleneck                1.3.5           py311hbed6279_0
brotli                    1.0.9                h5eee18b_7
brotli-bin                1.0.9                h5eee18b_7
brotlipy                  0.7.0           py311h5eee18b_1002
brunsli                   0.1                  h2531618_0
bzip2                     1.0.8                h7b6447c_0
c-ares                    1.19.1               h5eee18b_0
c-blosc2                  2.8.0                h6a678d5_0
ca-certificates           2023.08.22           h06a4308_0
certifi                   2023.11.17      py311h06a4308_0
certipy                   0.1.3                      py_0    conda-forge
cffi                      1.15.1          py311h5eee18b_3
cfitsio                   3.470                h5893167_7
chardet                   4.0.0           py311h06a4308_1003
charls                    2.2.0                h2531618_0
charset-normalizer        2.0.4              pyhd3eb1b0_0
click                     8.0.4           py311h06a4308_0
cloudpickle               2.2.1           py311h06a4308_0
clyent                    1.2.2           py311h06a4308_1
colorama                  0.4.6           py311h06a4308_0
colorcet                  3.0.1           py311h06a4308_0
comm                      0.1.2           py311h06a4308_0
conda                     23.7.4          py311h06a4308_0
conda-build               3.26.1          py311h06a4308_0
conda-content-trust       0.2.0           py311h06a4308_0
conda-index               0.3.0           py311h06a4308_0
conda-libmamba-solver     23.7.0          py311h06a4308_0
conda-pack                0.6.0              pyhd3eb1b0_0
conda-package-handling    2.2.0           py311h06a4308_0
conda-package-streaming   0.9.0           py311h06a4308_0
conda-repo-cli            1.0.75          py311h06a4308_0
conda-token               0.4.0              pyhd3eb1b0_0
conda-verify              3.4.2                      py_1
configurable-http-proxy   4.6.0                h06a4308_0
constantly                15.1.0          py311h06a4308_0
contourpy                 1.0.5           py311hdb19cb5_0
cookiecutter              1.7.3              pyhd3eb1b0_0
cryptography              41.0.3          py311hdda0065_0
cssselect                 1.1.0              pyhd3eb1b0_0
curl                      8.2.1                hdbd6064_0
cycler                    0.11.0             pyhd3eb1b0_0
cyrus-sasl                2.1.28               h52b45da_1
cytoolz                   0.12.0          py311h5eee18b_0
daal4py                   2023.1.1        py311h4cb112f_0
dal                       2023.1.1         hdb19cb5_48679
dask                      2023.6.0        py311h06a4308_0
dask-core                 2023.6.0        py311h06a4308_0
datasets                  2.12.0          py311h06a4308_0
datashader                0.15.2          py311h06a4308_0
datashape                 0.5.4           py311h06a4308_1
dav1d                     1.2.1                h5eee18b_0
dbus                      1.13.18              hb2f20db_0
debugpy                   1.6.7           py311h6a678d5_0
decorator                 5.1.1              pyhd3eb1b0_0
defusedxml                0.7.1              pyhd3eb1b0_0
diff-match-patch          20200713           pyhd3eb1b0_0
dill                      0.3.6           py311h06a4308_0
distributed               2023.6.0        py311h06a4308_0
docstring-to-markdown     0.11            py311h06a4308_0
docutils                  0.18.1          py311h06a4308_3
entrypoints               0.4             py311h06a4308_0
et_xmlfile                1.1.0           py311h06a4308_0
executing                 0.8.3              pyhd3eb1b0_0
expat                     2.5.0                h6a678d5_0
filelock                  3.9.0           py311h06a4308_0
flake8                    6.0.0           py311h06a4308_0
flask                     2.2.2           py311h06a4308_0
fmt                       9.1.0                hdb19cb5_0
font-ttf-dejavu-sans-mono 2.37                 hd3eb1b0_0
font-ttf-inconsolata      2.001                hcb22688_0
font-ttf-source-code-pro  2.030                hd3eb1b0_0
font-ttf-ubuntu           0.83                 h8b1ccd4_0
fontconfig                2.14.1               h4c34cd2_2
fonts-anaconda            1                    h8fa9717_0
fonttools                 4.25.0             pyhd3eb1b0_0
freetype                  2.12.1               h4a9f257_0
frozenlist                1.3.3           py311h5eee18b_0
fsspec                    2023.4.0        py311h06a4308_0
future                    0.18.3          py311h06a4308_0
gensim                    4.3.0           py311hba01205_1
gflags                    2.2.2                he6710b0_0
giflib                    5.2.1                h5eee18b_3
glib                      2.69.1               he621ea3_2
glob2                     0.7                pyhd3eb1b0_0
glog                      0.5.0                h2531618_0
gmp                       6.2.1                h295c915_3
gmpy2                     2.1.2           py311hc9b5ff0_0
greenlet                  2.0.1           py311h6a678d5_0
grpc-cpp                  1.48.2               he1ff14a_1
gst-plugins-base          1.14.1               h6a678d5_1
gstreamer                 1.14.1               h5eee18b_1
h5py                      3.9.0           py311hdd6beaf_0
hdf5                      1.12.1               h2b7332f_3
heapdict                  1.0.1              pyhd3eb1b0_0
holoviews                 1.17.1          py311h06a4308_0
huggingface_hub           0.15.1          py311h06a4308_0
hvplot                    0.8.4           py311h06a4308_0
hyperlink                 21.0.0             pyhd3eb1b0_0
icu                       58.2                 he6710b0_3
idna                      3.4             py311h06a4308_0
imagecodecs               2023.1.23       py311h8105a5c_0
imageio                   2.31.1          py311h06a4308_0
imagesize                 1.4.1           py311h06a4308_0
imbalanced-learn          0.10.1          py311h06a4308_1
importlib-metadata        6.0.0           py311h06a4308_0
importlib_metadata        6.0.0                hd3eb1b0_0
importlib_resources       6.1.1              pyhd8ed1ab_0    conda-forge
incremental               21.3.0             pyhd3eb1b0_0
inflection                0.5.1           py311h06a4308_0
iniconfig                 1.1.1              pyhd3eb1b0_0
intake                    0.6.8           py311h06a4308_0
intel-openmp              2023.1.0         hdb19cb5_46305
intervaltree              3.1.0              pyhd3eb1b0_0
ipykernel                 6.25.0          py311h92b7b1e_0
ipython                   8.15.0          py311h06a4308_0
ipython_genutils          0.2.0              pyhd3eb1b0_1
ipywidgets                8.0.4           py311h06a4308_0
isort                     5.9.3              pyhd3eb1b0_0
itemadapter               0.3.0              pyhd3eb1b0_0
itemloaders               1.0.4              pyhd3eb1b0_1
itsdangerous              2.0.1              pyhd3eb1b0_0
jaraco.classes            3.2.1              pyhd3eb1b0_0
jedi                      0.18.1          py311h06a4308_1
jeepney                   0.7.1              pyhd3eb1b0_0
jellyfish                 1.0.1           py311hb02cf49_0
jinja2                    3.1.2           py311h06a4308_0
jinja2-time               0.2.0              pyhd3eb1b0_3
jmespath                  0.10.0             pyhd3eb1b0_0
joblib                    1.2.0           py311h06a4308_0
jpeg                      9e                   h5eee18b_1
jq                        1.6               h27cfd23_1000
json5                     0.9.6              pyhd3eb1b0_0
jsonpatch                 1.32               pyhd3eb1b0_0
jsonpointer               2.1                pyhd3eb1b0_0
jsonschema                4.17.3          py311h06a4308_0
jupyter                   1.0.0           py311h06a4308_8
jupyter_client            7.4.9           py311h06a4308_0
jupyter_console           6.6.3           py311h06a4308_0
jupyter_core              5.3.0           py311h06a4308_0
jupyter_events            0.6.3           py311h06a4308_0
jupyter_server            1.23.4          py311h06a4308_0
jupyter_server_fileid     0.9.0           py311h06a4308_0
jupyter_server_ydoc       0.8.0           py311h06a4308_1
jupyter_telemetry         0.1.0              pyhd8ed1ab_1    conda-forge
jupyter_ydoc              0.2.4           py311h06a4308_0
jupyterhub                4.0.2              pyh31011fe_0    conda-forge
jupyterhub-base           4.0.2              pyh31011fe_0    conda-forge
jupyterlab                3.6.3           py311h06a4308_0
jupyterlab_pygments       0.1.2                      py_0
jupyterlab_server         2.22.0          py311h06a4308_0
jupyterlab_widgets        3.0.5           py311h06a4308_0
jxrlib                    1.1                  h7b6447c_2
kaleido-core              0.2.1                h7c8854e_0
keyring                   23.13.1         py311h06a4308_0
kiwisolver                1.4.4           py311h6a678d5_0
krb5                      1.20.1               h143b758_1
lazy-object-proxy         1.6.0           py311h5eee18b_0
lazy_loader               0.2             py311h06a4308_0
lcms2                     2.12                 h3be6417_0
ld_impl_linux-64          2.38                 h1181459_1
lerc                      3.0                  h295c915_0
libaec                    1.0.4                he6710b0_1
libarchive                3.6.2                h6ac8c49_2
libavif                   0.11.1               h5eee18b_0
libboost                  1.73.0              h28710b8_12
libbrotlicommon           1.0.9                h5eee18b_7
libbrotlidec              1.0.9                h5eee18b_7
libbrotlienc              1.0.9                h5eee18b_7
libclang                  14.0.6          default_hc6dbbc7_1
libclang13                14.0.6          default_he11475f_1
libcups                   2.4.2                h2d74bed_1
libcurl                   8.2.1                h251f7ec_0
libdeflate                1.17                 h5eee18b_0
libedit                   3.1.20221030         h5eee18b_0
libev                     4.33                 h7f8727e_1
libevent                  2.1.12               hdbd6064_1
libffi                    3.4.4                h6a678d5_0
libgcc-ng                 11.2.0               h1234567_1
libgfortran-ng            11.2.0               h00389a5_1
libgfortran5              11.2.0               h1234567_1
libgomp                   11.2.0               h1234567_1
liblief                   0.12.3               h6a678d5_0
libllvm14                 14.0.6               hdb19cb5_3
libmamba                  1.5.1                haf1ee3a_0
libmambapy                1.5.1           py311h2dafd23_0
libnghttp2                1.52.0               h2d74bed_1
libpng                    1.6.39               h5eee18b_0
libpq                     12.15                hdbd6064_1
libprotobuf               3.20.3               he621ea3_0
libsodium                 1.0.18               h7b6447c_0
libsolv                   0.7.24               he621ea3_0
libspatialindex           1.9.3                h2531618_0
libssh2                   1.10.0               hdbd6064_2
libstdcxx-ng              11.2.0               h1234567_1
libthrift                 0.15.0               h1795dd8_2
libtiff                   4.5.1                h6a678d5_0
libuuid                   1.41.5               h5eee18b_0
libuv                     1.44.2               h5eee18b_0
libwebp                   1.3.2                h11a3e52_0
libwebp-base              1.3.2                h5eee18b_0
libxcb                    1.15                 h7f8727e_0
libxkbcommon              1.0.1                h5eee18b_1
libxml2                   2.10.4               hcbfbd50_0
libxslt                   1.1.37               h2085143_0
libzopfli                 1.0.3                he6710b0_0
linkify-it-py             2.0.0           py311h06a4308_0
llvmlite                  0.40.0          py311he621ea3_0
locket                    1.0.0           py311h06a4308_0
lxml                      4.9.3           py311hdbbb534_0
lz4                       4.3.2           py311h5eee18b_0
lz4-c                     1.9.4                h6a678d5_0
lzo                       2.10                 h7b6447c_2
mako                      1.3.0              pyhd8ed1ab_0    conda-forge
markdown                  3.4.1           py311h06a4308_0
markdown-it-py            2.2.0           py311h06a4308_1
markupsafe                2.1.1           py311h5eee18b_0
mathjax                   2.7.5                h06a4308_0
matplotlib                3.7.2           py311h06a4308_0
matplotlib-base           3.7.2           py311ha02d727_0
matplotlib-inline         0.1.6           py311h06a4308_0
mccabe                    0.7.0              pyhd3eb1b0_0
mdit-py-plugins           0.3.0           py311h06a4308_0
mdurl                     0.1.0           py311h06a4308_0
mistune                   0.8.4           py311h5eee18b_1000
mkl                       2023.1.0         h213fc3f_46343
mkl-service               2.4.0           py311h5eee18b_1
mkl_fft                   1.3.8           py311h5eee18b_0
mkl_random                1.2.4           py311hdb19cb5_0
more-itertools            8.12.0             pyhd3eb1b0_0
mpc                       1.1.0                h10f8cd9_1
mpfr                      4.0.2                hb69a4c5_1
mpi                       1.0                       mpich
mpich                     4.1.1                hbae89fd_0
mpmath                    1.3.0           py311h06a4308_0
msgpack-python            1.0.3           py311hdb19cb5_0
multidict                 6.0.2           py311h5eee18b_0
multipledispatch          0.6.0           py311h06a4308_0
multiprocess              0.70.14         py311h06a4308_0
munkres                   1.1.4                      py_0
mypy_extensions           1.0.0           py311h06a4308_0
mysql                     5.7.24               h721c034_2
navigator-updater         0.4.0           py311h06a4308_1
nbclassic                 0.5.5           py311h06a4308_0
nbclient                  0.5.13          py311h06a4308_0
nbconvert                 6.5.4           py311h06a4308_0
nbformat                  5.9.2           py311h06a4308_0
ncurses                   6.4                  h6a678d5_0
nest-asyncio              1.5.6           py311h06a4308_0
networkx                  3.1             py311h06a4308_0
nltk                      3.8.1           py311h06a4308_0
nodejs                    18.16.0              h2d74bed_0
notebook                  6.5.4           py311h06a4308_1
notebook-shim             0.2.2           py311h06a4308_0
nspr                      4.35                 h6a678d5_0
nss                       3.89.1               h6a678d5_0
numba                     0.57.1          py311ha02d727_0
numexpr                   2.8.4           py311h65dcdc2_1
numpy                     1.24.3          py311h08b1b3b_1
numpy-base                1.24.3          py311hf175353_1
numpydoc                  1.5.0           py311h06a4308_0
oauthlib                  3.2.2              pyhd8ed1ab_0    conda-forge
oniguruma                 6.9.7.1              h27cfd23_0
openjpeg                  2.4.0                h3ad879b_0
openpyxl                  3.0.10          py311h5eee18b_0
openssl                   3.0.12               h7f8727e_0
orc                       1.7.4                hb3bc3d3_1
packaging                 23.1            py311h06a4308_0
pamela                    1.1.0              pyh1a96a4e_0    conda-forge
pandas                    2.0.3           py311ha02d727_0
pandocfilters             1.5.0              pyhd3eb1b0_0
panel                     1.2.3           py311h06a4308_0
param                     1.13.0          py311h06a4308_0
parsel                    1.6.0           py311h06a4308_0
parso                     0.8.3              pyhd3eb1b0_0
partd                     1.4.0           py311h06a4308_0
patch                     2.7.6             h7b6447c_1001
patchelf                  0.17.2               h6a678d5_0
pathlib                   1.0.1              pyhd3eb1b0_1
pathspec                  0.10.3          py311h06a4308_0
patsy                     0.5.3           py311h06a4308_0
pcre                      8.45                 h295c915_0
pcre2                     10.42                hebb0a14_0
pep8                      1.7.1           py311h06a4308_1
pexpect                   4.8.0              pyhd3eb1b0_3
pickleshare               0.7.5           pyhd3eb1b0_1003
pillow                    9.4.0           py311h6a678d5_1
pip                       23.2.1          py311h06a4308_0
pkce                      1.0.3           py311h06a4308_0
pkginfo                   1.9.6           py311h06a4308_0
platformdirs              3.10.0          py311h06a4308_0
plotly                    5.9.0           py311h06a4308_0
pluggy                    1.0.0           py311h06a4308_1
ply                       3.11            py311h06a4308_0
poyo                      0.5.0              pyhd3eb1b0_0
prometheus_client         0.14.1          py311h06a4308_0
prompt-toolkit            3.0.36          py311h06a4308_0
prompt_toolkit            3.0.36               hd3eb1b0_0
protego                   0.1.16                     py_0
psutil                    5.9.0           py311h5eee18b_0
ptyprocess                0.7.0              pyhd3eb1b0_2
pure_eval                 0.2.2              pyhd3eb1b0_0
py-cpuinfo                8.0.0              pyhd3eb1b0_1
py-lief                   0.12.3          py311h6a678d5_0
pyarrow                   11.0.0          py311hd8e8d9b_1
pyasn1                    0.4.8              pyhd3eb1b0_0
pyasn1-modules            0.2.8                      py_0
pybind11-abi              4                    hd3eb1b0_1
pycodestyle               2.10.0          py311h06a4308_0
pycosat                   0.6.4           py311h5eee18b_0
pycparser                 2.21               pyhd3eb1b0_0
pyct                      0.5.0           py311h06a4308_0
pycurl                    7.45.2          py311hdbd6064_1
pydantic                  1.10.8          py311h5eee18b_0
pydispatcher              2.0.5           py311h06a4308_2
pydocstyle                6.3.0           py311h06a4308_0
pyerfa                    2.0.0           py311h5eee18b_0
pyflakes                  3.0.1           py311h06a4308_0
pygments                  2.15.1          py311h06a4308_1
pyjwt                     2.4.0           py311h06a4308_0
pylint                    2.16.2          py311h06a4308_0
pylint-venv               2.3.0           py311h06a4308_0
pyls-spyder               0.4.0              pyhd3eb1b0_0
pyodbc                    4.0.34          py311h6a678d5_0
pyopenssl                 23.2.0          py311h06a4308_0
pyparsing                 3.0.9           py311h06a4308_0
pyqt                      5.15.7          py311h6a678d5_0
pyqt5-sip                 12.11.0         py311h6a678d5_0
pyqtwebengine             5.15.7          py311h6a678d5_0
pyrsistent                0.18.0          py311h5eee18b_0
pysocks                   1.7.1           py311h06a4308_0
pytables                  3.8.0           py311hb8ae3fc_3
pytest                    7.4.0           py311h06a4308_0
python                    3.11.5               h955ad1f_0
python-dateutil           2.8.2              pyhd3eb1b0_0
python-dotenv             0.21.0          py311h06a4308_0
python-fastjsonschema     2.16.2          py311h06a4308_0
python-json-logger        2.0.7           py311h06a4308_0
python-kaleido            0.2.1           py311h06a4308_0
python-libarchive-c       2.9                pyhd3eb1b0_1
python-lmdb               1.4.1           py311h6a678d5_0
python-lsp-black          1.2.1           py311h06a4308_0
python-lsp-jsonrpc        1.0.0              pyhd3eb1b0_0
python-lsp-server         1.7.2           py311h06a4308_0
python-slugify            5.0.2              pyhd3eb1b0_0
python-snappy             0.6.1           py311h6a678d5_0
python-tzdata             2023.3             pyhd3eb1b0_0
python-xxhash             2.0.2           py311h5eee18b_1
pytoolconfig              1.2.5           py311h06a4308_1
pytz                      2023.3.post1    py311h06a4308_0
pyviz_comms               2.3.0           py311h06a4308_0
pywavelets                1.4.1           py311h5eee18b_0
pyxdg                     0.27               pyhd3eb1b0_0
pyyaml                    6.0             py311h5eee18b_1
pyzmq                     23.2.0          py311h6a678d5_0
qdarkstyle                3.0.2              pyhd3eb1b0_0
qstylizer                 0.2.2           py311h06a4308_0
qt-main                   5.15.2               h7358343_9
qt-webengine              5.15.9               h9ab4d14_7
qtawesome                 1.2.2           py311h06a4308_0
qtconsole                 5.4.2           py311h06a4308_0
qtpy                      2.2.0           py311h06a4308_0
qtwebkit                  5.212                h3fafdc1_5
queuelib                  1.5.0           py311h06a4308_0
re2                       2022.04.01           h295c915_0
readline                  8.2                  h5eee18b_0
regex                     2022.7.9        py311h5eee18b_0
reproc                    14.2.4               h295c915_1
reproc-cpp                14.2.4               h295c915_1
requests                  2.31.0          py311h06a4308_0
requests-file             1.5.1              pyhd3eb1b0_0
requests-toolbelt         1.0.0           py311h06a4308_0
responses                 0.13.3             pyhd3eb1b0_0
rfc3339-validator         0.1.4           py311h06a4308_0
rfc3986-validator         0.1.1           py311h06a4308_0
rope                      1.7.0           py311h06a4308_0
rtree                     1.0.1           py311h06a4308_0
ruamel.yaml               0.17.21         py311h5eee18b_0
ruamel_yaml               0.17.21         py311h5eee18b_0
s3fs                      2023.4.0        py311h06a4308_0
safetensors               0.3.2           py311hb02cf49_0
scikit-image              0.20.0          py311h6a678d5_0
scikit-learn              1.3.0           py311ha02d727_0
scikit-learn-intelex      2023.1.1        py311h06a4308_0
scipy                     1.11.1          py311h08b1b3b_0
scrapy                    2.8.0           py311h06a4308_0
seaborn                   0.12.2          py311h06a4308_0
secretstorage             3.3.1           py311h06a4308_1
send2trash                1.8.0              pyhd3eb1b0_1
service_identity          18.1.0             pyhd3eb1b0_1
setuptools                68.0.0          py311h06a4308_0
sip                       6.6.2           py311h6a678d5_0
six                       1.16.0             pyhd3eb1b0_1
smart_open                5.2.1           py311h06a4308_0
snappy                    1.1.9                h295c915_0
sniffio                   1.2.0           py311h06a4308_1
snowballstemmer           2.2.0              pyhd3eb1b0_0
sortedcontainers          2.4.0              pyhd3eb1b0_0
soupsieve                 2.4             py311h06a4308_0
sphinx                    5.0.2           py311h06a4308_0
sphinxcontrib-applehelp   1.0.2              pyhd3eb1b0_0
sphinxcontrib-devhelp     1.0.2              pyhd3eb1b0_0
sphinxcontrib-htmlhelp    2.0.0              pyhd3eb1b0_0
sphinxcontrib-jsmath      1.0.1              pyhd3eb1b0_0
sphinxcontrib-qthelp      1.0.3              pyhd3eb1b0_0
sphinxcontrib-serializinghtml 1.1.5              pyhd3eb1b0_0
spyder                    5.4.3           py311h06a4308_1
spyder-kernels            2.4.4           py311h06a4308_0
sqlalchemy                1.4.39          py311h5eee18b_0
sqlite                    3.41.2               h5eee18b_0
stack_data                0.2.0              pyhd3eb1b0_0
statsmodels               0.14.0          py311hf4808d0_0
sympy                     1.11.1          py311h06a4308_0
tabulate                  0.8.10          py311h06a4308_0
tbb                       2021.8.0             hdb19cb5_0
tbb4py                    2021.8.0        py311hdb19cb5_0
tblib                     1.7.0              pyhd3eb1b0_0
tenacity                  8.2.2           py311h06a4308_0
terminado                 0.17.1          py311h06a4308_0
text-unidecode            1.3                pyhd3eb1b0_0
textdistance              4.2.1              pyhd3eb1b0_0
threadpoolctl             2.2.0              pyh0d69192_0
three-merge               0.1.1              pyhd3eb1b0_0
tifffile                  2023.4.12       py311h06a4308_0
tinycss2                  1.2.1           py311h06a4308_0
tk                        8.6.12               h1ccaba5_0
tldextract                3.2.0              pyhd3eb1b0_0
tokenizers                0.13.2          py311h22610ee_1
toml                      0.10.2             pyhd3eb1b0_0
tomlkit                   0.11.1          py311h06a4308_0
toolz                     0.12.0          py311h06a4308_0
tornado                   6.3.2           py311h5eee18b_0
tqdm                      4.65.0          py311h92b7b1e_0
traitlets                 5.7.1           py311h06a4308_0
transformers              4.32.1          py311h06a4308_0
twisted                   22.10.0         py311h5eee18b_0
typing-extensions         4.7.1           py311h06a4308_0
typing_extensions         4.7.1           py311h06a4308_0
tzdata                    2023c                h04d1e81_0
uc-micro-py               1.0.1           py311h06a4308_0
ujson                     5.4.0           py311h6a678d5_0
unidecode                 1.2.0              pyhd3eb1b0_0
unixodbc                  2.3.11               h5eee18b_0
urllib3                   1.26.16         py311h06a4308_0
utf8proc                  2.6.1                h27cfd23_0
w3lib                     1.21.0             pyhd3eb1b0_0
watchdog                  2.1.6           py311h06a4308_0
wcwidth                   0.2.5              pyhd3eb1b0_0
webencodings              0.5.1           py311h06a4308_1
websocket-client          0.58.0          py311h06a4308_4
werkzeug                  2.2.3           py311h06a4308_0
whatthepatch              1.0.2           py311h06a4308_0
wheel                     0.38.4          py311h06a4308_0
widgetsnbextension        4.0.5           py311h06a4308_0
wrapt                     1.14.1          py311h5eee18b_0
wurlitzer                 3.0.2           py311h06a4308_0
xarray                    2023.6.0        py311h06a4308_0
xxhash                    0.8.0                h7f8727e_3
xyzservices               2022.9.0        py311h06a4308_1
xz                        5.4.2                h5eee18b_0
y-py                      0.5.9           py311h52d8a92_0
yaml                      0.2.5                h7b6447c_0
yaml-cpp                  0.7.0                h295c915_1
yapf                      0.31.0             pyhd3eb1b0_0
yarl                      1.8.1           py311h5eee18b_0
ypy-websocket             0.8.2           py311h06a4308_0
zeromq                    4.3.4                h2531618_0
zfp                       1.0.0                h6a678d5_0
zict                      2.2.0           py311h06a4308_0
zipp                      3.11.0          py311h06a4308_0
zlib                      1.2.13               h5eee18b_0
zlib-ng                   2.0.7                h5eee18b_0
zope                      1.0             py311h06a4308_1
zope.interface            5.4.0           py311h5eee18b_0
zstandard                 0.19.0          py311h5eee18b_0
zstd                      1.5.5                hc292b87_0
```
</details>

<details><summary>Configuration</summary>
<!--
For JupyterHub, especially include information such as what Spawner and Authenticator are being used.
Be careful not to share any sensitive information.
You can paste jupyterhub_config.py below.
To exclude lots of comments and empty lines from auto-generated jupyterhub_config.py, you can do:
    grep -v '\(^#\|^[[:space:]]*$\)' jupyterhub_config.py
-->

```python
c = get_config()  #noqa
c.PAMAuthenticator.allowed_groups = {"jupyter"}
```
</details>

<details><summary>Logs</summary>

```
[I 2023-12-09 12:00:38.248 JupyterHub app:2859] Running JupyterHub version 4.0.2
[I 2023-12-09 12:00:38.248 JupyterHub app:2889] Using Authenticator: jupyterhub.auth.PAMAuthenticator-4.0.2
[I 2023-12-09 12:00:38.248 JupyterHub app:2889] Using Spawner: jupyterhub.spawner.LocalProcessSpawner-4.0.2
[I 2023-12-09 12:00:38.248 JupyterHub app:2889] Using Proxy: jupyterhub.proxy.ConfigurableHTTPProxy-4.0.2
[I 2023-12-09 12:00:38.253 JupyterHub app:1664] Loading cookie_secret from /opt/docker/jupyterhub_cookie_secret
[I 2023-12-09 12:00:38.272 JupyterHub proxy:556] Generating new CONFIGPROXY_AUTH_TOKEN
[I 2023-12-09 12:00:38.276 JupyterHub app:1984] Not using allowed_users. Any authenticated user will be allowed.
[I 2023-12-09 12:00:38.284 JupyterHub app:2928] Initialized 0 spawners in 0.001 seconds
[I 2023-12-09 12:00:38.286 JupyterHub metrics:278] Found 4 active users in the last ActiveUserPeriods.twenty_four_hours
[I 2023-12-09 12:00:38.286 JupyterHub metrics:278] Found 4 active users in the last ActiveUserPeriods.seven_days
[I 2023-12-09 12:00:38.286 JupyterHub metrics:278] Found 4 active users in the last ActiveUserPeriods.thirty_days
[W 2023-12-09 12:00:38.287 JupyterHub proxy:746] Running JupyterHub without SSL.  I hope there is SSL termination happening somewhere else...
[I 2023-12-09 12:00:38.287 JupyterHub proxy:750] Starting proxy @ http://:8000
12:00:38.395 [ConfigProxy] info: Proxying http://*:8000 to (no default)
12:00:38.396 [ConfigProxy] info: Proxy API at http://127.0.0.1:8001/api/routes
[I 2023-12-09 12:00:38.492 JupyterHub app:3178] Hub API listening on http://127.0.0.1:8081/hub/
12:00:38.492 [ConfigProxy] info: 200 GET /api/routes
12:00:38.493 [ConfigProxy] info: 200 GET /api/routes
[I 2023-12-09 12:00:38.493 JupyterHub proxy:477] Adding route for Hub: / => http://127.0.0.1:8081
12:00:38.494 [ConfigProxy] info: Adding route / -> http://127.0.0.1:8081
12:00:38.494 [ConfigProxy] info: Route added / -> http://127.0.0.1:8081
12:00:38.494 [ConfigProxy] info: 201 POST /api/routes/
[I 2023-12-09 12:00:38.495 JupyterHub app:3245] JupyterHub is now running at http://:8000
[W 2023-12-09 12:00:44.988 JupyterHub auth:533] User 'testuser' not allowed.
[W 2023-12-09 12:00:44.988 JupyterHub base:843] Failed login for testuser
[I 2023-12-09 12:00:44.998 JupyterHub log:191] 200 POST /hub/login?next= (@::1) 29.80ms
^C[C 2023-12-09 12:00:54.478 JupyterHub app:3336] Received signal SIGINT, initiating shutdown...
[I 2023-12-09 12:00:54.478 JupyterHub app:2981] Cleaning up single-user servers...
[I 2023-12-09 12:00:54.478 JupyterHub proxy:820] Cleaning up proxy[707]...
[I 2023-12-09 12:00:54.479 JupyterHub app:3013] ...done
```

</details>



Discussion:
Thank you for opening your first issue in this project! Engagement like this is essential for open source projects! :hugs:
<br>If you haven't done so already, check out [Jupyter's Code of Conduct](https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md). Also, please try to follow the issue template as it helps other other community members to contribute more effectively.
![welcome](https://raw.githubusercontent.com/jupyterhub/.github/master/images/welcome.jpg)
You can meet the other [Jovyans](https://jupyter.readthedocs.io/en/latest/community/content-community.html?highlight=jovyan#what-is-a-jovyan) by joining our [Discourse forum](http://discourse.jupyter.org/). There is also an intro thread there where you can stop by and say Hi! :wave:
<br>Welcome to the Jupyter community! :tada:

Thanks for reporting! This is definitely not the intended behavior, and we in fact had a recent related fix for spawner gids in #4628. The same change (`os.getgrouplist` instead of checking `grp.gr_mem`) should work for LocalAuthenticator, as well. Would you like to try a PR?


Resolving patch:
diff --git a/jupyterhub/auth.py b/jupyterhub/auth.py
--- a/jupyterhub/auth.py
+++ b/jupyterhub/auth.py
@@ -1115,13 +1115,16 @@ def check_allowed_groups(self, username, authentication=None):
         """
         if not self.allowed_groups:
             return False
+        user_group_gids = set(
+            self._getgrouplist(username, self._getpwnam(username).pw_gid)
+        )
         for grnam in self.allowed_groups:
             try:
                 group = self._getgrnam(grnam)
             except KeyError:
                 self.log.error('No such group: [%s]' % grnam)
                 continue
-            if username in group.gr_mem:
+            if group.gr_gid in user_group_gids:
                 return True
         return False
 


Test patch:
diff --git a/jupyterhub/tests/test_auth.py b/jupyterhub/tests/test_auth.py
--- a/jupyterhub/tests/test_auth.py
+++ b/jupyterhub/tests/test_auth.py
@@ -165,21 +165,35 @@ async def test_pam_auth_allowed():
 
 
 async def test_pam_auth_allowed_groups():
-    def getgrnam(name):
-        return MockStructGroup('grp', ['kaylee'])
-
-    authenticator = MockPAMAuthenticator(allowed_groups={'group'}, allow_all=False)
+    class TestAuthenticator(MockPAMAuthenticator):
+        @staticmethod
+        def _getpwnam(name):
+            return MockStructPasswd(name=name)
+
+        @staticmethod
+        def _getgrnam(name):
+            if name == "group":
+                return MockStructGroup('grp', ['kaylee'], gid=1234)
+            else:
+                return None
+
+        @staticmethod
+        def _getgrouplist(username, gid):
+            gids = [gid]
+            if username == "kaylee":
+                gids.append(1234)
+            return gids
+
+    authenticator = TestAuthenticator(allowed_groups={'group'}, allow_all=False)
 
-    with mock.patch.object(authenticator, '_getgrnam', getgrnam):
-        authorized = await authenticator.get_authenticated_user(
-            None, {'username': 'kaylee', 'password': 'kaylee'}
-        )
+    authorized = await authenticator.get_authenticated_user(
+        None, {'username': 'kaylee', 'password': 'kaylee'}
+    )
     assert authorized['name'] == 'kaylee'
 
-    with mock.patch.object(authenticator, '_getgrnam', getgrnam):
-        authorized = await authenticator.get_authenticated_user(
-            None, {'username': 'mal', 'password': 'mal'}
-        )
+    authorized = await authenticator.get_authenticated_user(
+        None, {'username': 'mal', 'password': 'mal'}
+    )
     assert authorized is None
 
 
@@ -270,6 +284,7 @@ async def test_pam_auth_no_such_group():
     authenticator = MockPAMAuthenticator(
         allowed_groups={'nosuchcrazygroup'},
     )
+    authenticator._getpwnam = MockStructPasswd
     authorized = await authenticator.get_authenticated_user(
         None, {'username': 'kaylee', 'password': 'kaylee'}
     )