Forceu / Gokapi

Lightweight selfhosted Firefox Send alternative without public upload. AWS S3 supported.
GNU Affero General Public License v3.0
1.49k stars 57 forks source link

Bug: Gokapi crashes if OIDC returns null in groups #198

Closed domingo13 closed 2 months ago

domingo13 commented 2 months ago

I have setup OIDC authentication with a limit on group membership.

If a user is not in a group the returned value is "null" which crashes Gokapi consistently:

██████  ██████   ██  ██  █████  ██████  ██  ██       ██    ██ ██  ██  ██   ██ ██   ██ ██  ██  ███ ██  ██ █████   ███████ ██████  ██  ██  ██ ██  ██ ██  ██  ██   ██ ██      ██   ██████   ██████  ██  ██ ██  ██ ██  ██                                       

Gokapi v1.9.0 starting Saving new files to local storage Binding webserver to :53842 Webserver can be accessed at https://share.xxx/admin Press CTRL+C to stop Gokapi 2024/07/28 18:08:30 http: panic serving 172.23.0.2:50044: interface conversion: interface {} is nil, not []interface {} goroutine 73 [running]: net/http.(conn).serve.func1() /usr/local/go/src/net/http/server.go:1898 +0xbe panic({0xdaf940?, 0xc0004fd4d0?}) /usr/local/go/src/runtime/panic.go:770 +0x132 github.com/forceu/gokapi/internal/webserver/authentication.extractOauthGroups({0x2cb1d40, 0xc000486640}, {0xc0003c82a6, 0x6}) /compile/internal/webserver/authentication/Authentication.go:174 +0x285 github.com/forceu/gokapi/internal/webserver/authentication.CheckOauthUserAndRedirect({{0xc000533020, 0x24}, {0x0, 0x0}, {0x2cb1d40, 0xc000486640}}, {0x2cb66d8, 0xc0000a0000}) /compile/internal/webserver/authentication/Authentication.go:237 +0xfb github.com/forceu/gokapi/internal/webserver/authentication/oauth.HandlerCallback({0x2cb66d8, 0xc0000a0000}, 0xc0003aa120) /compile/internal/webserver/authentication/oauth/Oauth.go:105 +0x2bd net/http.HandlerFunc.ServeHTTP(0xc00048f1e0?, {0x2cb66d8?, 0xc0000a0000?}, 0x9b17da?) /usr/local/go/src/net/http/server.go:2166 +0x29 net/http.(ServeMux).ServeHTTP(0x46a6d9?, {0x2cb66d8, 0xc0000a0000}, 0xc0003aa120) /usr/local/go/src/net/http/server.go:2683 +0x1ad net/http.serverHandler.ServeHTTP({0xc00062ec30?}, {0x2cb66d8?, 0xc0000a0000?}, 0x6?) /usr/local/go/src/net/http/server.go:3137 +0x8e net/http.(conn).serve(0xc0003c67e0, {0x2cb6f88, 0xc00062e420}) /usr/local/go/src/net/http/server.go:2039 +0x5e8 created by net/http.(Server).Serve in goroutine 28 /usr/local/go/src/net/http/server.go:3285 +0x4b4 Shutting down...

If I use a user with any group membership this doesn't occur, and the right membership gives the user access.

The authentication server is Authelia, the Gokapi config looks like this:

{ "Authentication": { "Method": 1, "SaltAdmin": "xx", "SaltFiles": "xx", "Username": "zz", "Password": "zz", "HeaderKey": "", "OauthProvider": "https://auth.xxx", "OAuthClientId": "gokapi", "OAuthClientSecret": "xxx", "OauthUserScope": "", "OauthGroupScope": "groups", "OAuthRecheckInterval": 12, "HeaderUsers": null, "OAuthGroups": [ "gokapi" ], "OauthUsers": [] }, "Port": ":53842", "ServerUrl": "https://share.xxx/", "RedirectUrl": "https://lnxgeek.org/", "PublicName": "Gokapi", "DataDir": "data", "DatabaseUrl": "redis://redis:6379?prefix=gokapi_", "ConfigVersion": 21, "LengthId": 15, "MaxFileSizeMB": 102400, "MaxMemory": 50, "ChunkSize": 45, "MaxParallelUploads": 4, "Encryption": { "Level": 0, "Cipher": null, "Salt": "", "Checksum": "", "ChecksumSalt": "" }, "UseSsl": false, "PicturesAlwaysLocal": false, "SaveIp": true, "IncludeFilename": true }

domingo13 commented 2 months ago

Here is the response from Authelia when it crashes:

{"amr":["pwd","otp","mfa"],"aud":["gokapi"],"auth_time":1722190082,"azp":"gokapi","client_id":"gokapi","groups":null,"iat":1722190088,"iss":"https://auth.xxx","name":"User1","preferred_username":"user1","sub":"316697f5-7f64-4bd9-ac8b-bc84d7df423a"}

Forceu commented 2 months ago

Thank you for the bug report! I will have a look at it tomorrow

Forceu commented 2 months ago

@domingo13 Unfortunately I was unable to reproduce the problem with Authelia. Can you post your (redacted) Authelia configuration as well? Also what version of Gokapi and Authelia are you using? And have you been following this guide? https://gokapi.readthedocs.io/en/stable/examples.html#server-configuration

domingo13 commented 2 months ago

Sure :-)

Gokapi v. 1.9.0 Authelia v. 4.38.9

This is the Authelia configuration:


theme: auto default_2fa_method: totp default_redirection_url: https://auth.xxx server: address: tcp://0.0.0.0:9091/ log: level: info totp: disable: false algorithm: sha1 digits: 6 period: 30 skew: 1 secret_size: 32 webauthn: disable: false display_name: 'Authelia' timeout: 60s attestation_conveyance_preference: indirect user_verification: preferred authentication_backend: password_reset: disable: false refresh_interval: 5m ldap: implementation: custom timeout: 5s start_tls: false attributes: username: uid display_name: displayName group_name: cn mail: mail additional_users_dn: ou=people users_filter: "(&({username_attribute}={input})(objectClass=person))" additional_groups_dn: ou=groups groups_filter: "(member={dn})" password_policy: standard: enabled: false min_length: 8 max_length: 0 require_uppercase: true require_lowercase: true require_number: true require_special: false access_control: default_policy: two_factor session: name: authelia_session redis: host: redis port: 6379 regulation: max_retries: 3 find_time: 2m ban_time: 5m storage: local: path: /config/db.sqlite3 notifier: disable_startup_check: false

identity_providers: oidc: enable_client_debug_messages: true

cors:
  endpoints:
    - authorization
    - token
    - revocation
    - introspection
    - userinfo
  allowed_origins:
    - https://auth.xxx
  allowed_origins_from_client_redirect_uris: false
clients:

  - client_id: 'xxx'
    client_name: 'Gokapi'
    client_secret: '$argon2xxx'
    public: false
    authorization_policy: 'two_factor'
    redirect_uris:
      - 'https://share.xxx/oauth-callback'
    scopes:
      - 'openid'
      - 'profile'
      - 'email'
      - 'groups'
    userinfo_signed_response_alg: 'none'
    token_endpoint_auth_method: 'client_secret_basic'
    consent_mode: 'auto'
    pre_configured_consent_duration: '1M'

All the secrets are provided by envirionments in the docker-compose file.

I tried to follow the guide as good as I could.

Let me know if you need anything else.

Forceu commented 2 months ago

Okay, I assume the problem is your group filter for LDAP. In the Authelia documentation they use

 additional_groups_dn: 'OU=groups'
    groups_filter: '(&(member={dn})(objectClass=groupOfNames))'
    group_search_mode: 'filter' 

Does that work? At least that would explain why the groups are sent as null instead of an empty array.

Forceu commented 2 months ago

Fixed in 3130917

domingo13 commented 2 months ago

It seem to be the way Authelia handles an emtpy object when the ldap search doesn't return anything. I have tried your version of group filter and one which matches lldap (which is the backend) "(&(member={dn})(objectClass=groupOfUniqueNames))" but it ends up the same place.

Looking forward to try out your fix :-)

Forceu commented 2 months ago

Yes, that is indeed a strange behaviour. I don't think it is supposed to be that way, in the end I was able to reproduce it even without LDAP. I might open an issue at their project later on.

If you are using the docker image, you can already try the fix with the tag gokapi:latest-dev

domingo13 commented 2 months ago

And it does the trick :-) No more crashing

Forceu commented 2 months ago

Great to hear, thanks! :)