Smartcard configuration against Active Directory NoMethodError "(undefined method `dn' for nil:NilClass):" Results in a 500 error

Searched all over and cannot find anything very similar.

GitLab-ee 17.7.0 Self-Managed. We use our instance in the DoD and wish to use the smartcard capabilities with LDAP/Active Directory. Regular usernames and password work with the base specified, however, giving GitLab our smartcard cert results in an error I am not familiar with.

My LDAP configuration
###! **remember to close this block with 'EOS' below** gitlab_rails['ldap_servers'] = YAML.load <<-'EOS' main: # 'main' is the GitLab 'provider ID' of this LDAP server label: 'redacted' uid: 'sAMAaccountName' host: 'redacted' port: 636 encryption: 'simple_tls' verify_certificates: true ca_file: '/etc/gitlab/trusted-certs/tls-ca-bundle.pem' smartcard_auth: optional smartcard_ad_cert_field: 'userPrincipalName' smartcard_ad_cert_format: 'principal_name' timeout: 30 active_directory: true allow_username_or_email_login: false attributes: username: 'sAMAccountName' email: 'mail' name: 'displayName' lowercase_usernames: true block_auto_created_users: false base: 'redacted'
Error Message
`==> /var/log/gitlab/gitlab-rails/production.log <==

NoMethodError (undefined method `dn’ for nil:NilClass):

ee/lib/gitlab/auth/smartcard/ldap_certificate.rb:20:in find_user' ee/lib/gitlab/auth/smartcard/base.rb:36:in find_or_create_user’
ee/app/controllers/smartcard_controller.rb:66:in sign_in_with' ee/app/controllers/smartcard_controller.rb:26:in verify_certificate’
actionpack (7.0.8.6) lib/action_controller/metal/basic_implicit_render.rb:6:in send_action' actionpack (7.0.8.6) lib/abstract_controller/base.rb:215:in process_action’
actionpack (7.0.8.6) lib/action_controller/metal/rendering.rb:165:in process_action' actionpack (7.0.8.6) lib/abstract_controller/callbacks.rb:234:in block in process_action’
activesupport (7.0.8.6) lib/active_support/callbacks.rb:118:in block in run_callbacks' lib/gitlab/ip_address_state.rb:11:in with’
ee/app/controllers/ee/application_controller.rb:45:in set_current_ip_address' activesupport (7.0.8.6) lib/active_support/callbacks.rb:127:in block in run_callbacks’
app/controllers/application_controller.rb:506:in set_current_admin' activesupport (7.0.8.6) lib/active_support/callbacks.rb:127:in block in run_callbacks’
lib/gitlab/session.rb:11:in with_session' app/controllers/application_controller.rb:496:in set_session_storage’
activesupport (7.0.8.6) lib/active_support/callbacks.rb:127:in block in run_callbacks' lib/gitlab/i18n.rb:114:in with_locale’
app/controllers/application_controller.rb:489:in set_locale' activesupport (7.0.8.6) lib/active_support/callbacks.rb:127:in block in run_callbacks’
app/controllers/application_controller.rb:480:in set_current_context' activesupport (7.0.8.6) lib/active_support/callbacks.rb:127:in block in run_callbacks’
marginalia (1.11.1) lib/marginalia.rb:109:in record_query_comment' activesupport (7.0.8.6) lib/active_support/callbacks.rb:127:in block in run_callbacks’
sentry-rails (5.21.0) lib/sentry/rails/controller_transaction.rb:32:in block in sentry_around_action' sentry-ruby (5.21.0) lib/sentry/hub.rb:108:in with_child_span’
sentry-ruby (5.21.0) lib/sentry-ruby.rb:499:in with_child_span' sentry-rails (5.21.0) lib/sentry/rails/controller_transaction.rb:18:in sentry_around_action’
activesupport (7.0.8.6) lib/active_support/callbacks.rb:127:in block in run_callbacks' activesupport (7.0.8.6) lib/active_support/callbacks.rb:138:in run_callbacks’
actionpack (7.0.8.6) lib/abstract_controller/callbacks.rb:233:in process_action' actionpack (7.0.8.6) lib/action_controller/metal/rescue.rb:23:in process_action’
actionpack (7.0.8.6) lib/action_controller/metal/instrumentation.rb:67:in block in process_action' activesupport (7.0.8.6) lib/active_support/notifications.rb:206:in block in instrument’
activesupport (7.0.8.6) lib/active_support/notifications/instrumenter.rb:24:in instrument' activesupport (7.0.8.6) lib/active_support/notifications.rb:206:in instrument’
actionpack (7.0.8.6) lib/action_controller/metal/instrumentation.rb:66:in process_action' actionpack (7.0.8.6) lib/action_controller/metal/params_wrapper.rb:259:in process_action’
activerecord (7.0.8.6) lib/active_record/railties/controller_runtime.rb:27:in process_action' actionpack (7.0.8.6) lib/abstract_controller/base.rb:151:in process’
actionview (7.0.8.6) lib/action_view/rendering.rb:39:in process' actionpack (7.0.8.6) lib/action_controller/metal.rb:188:in dispatch’
actionpack (7.0.8.6) lib/action_controller/metal.rb:249:in block in dispatch' lib/gitlab/middleware/action_controller_static_context.rb:23:in call’
actionpack (7.0.8.6) lib/action_controller/metal.rb:249:in dispatch' actionpack (7.0.8.6) lib/action_dispatch/routing/route_set.rb:49:in dispatch’
actionpack (7.0.8.6) lib/action_dispatch/routing/route_set.rb:32:in serve' actionpack (7.0.8.6) lib/action_dispatch/journey/router.rb:50:in block in serve’
actionpack (7.0.8.6) lib/action_dispatch/journey/router.rb:32:in each' actionpack (7.0.8.6) lib/action_dispatch/journey/router.rb:32:in serve’
actionpack (7.0.8.6) lib/action_dispatch/routing/route_set.rb:852:in call' gitlab-experiment (0.9.1) lib/gitlab/experiment/middleware.rb:19:in call’
omniauth (2.1.0) lib/omniauth/strategy.rb:202:in call!' omniauth (2.1.0) lib/omniauth/strategy.rb:169:in call’
flipper (0.26.2) lib/flipper/middleware/memoizer.rb:72:in memoized_call' flipper (0.26.2) lib/flipper/middleware/memoizer.rb:37:in call’
lib/gitlab/metrics/elasticsearch_rack_middleware.rb:16:in call' lib/gitlab/middleware/sidekiq_shard_awareness_validation.rb:20:in block in call’
lib/gitlab/sidekiq_sharding/validator.rb:42:in enabled' lib/gitlab/middleware/sidekiq_shard_awareness_validation.rb:20:in call’
lib/gitlab/middleware/memory_report.rb:13:in call' lib/gitlab/middleware/speedscope.rb:13:in call’
lib/gitlab/database/load_balancing/rack_middleware.rb:23:in call' lib/gitlab/middleware/rails_queue_duration.rb:33:in call’
lib/gitlab/etag_caching/middleware.rb:21:in call' lib/gitlab/metrics/rack_middleware.rb:16:in block in call’
lib/gitlab/metrics/web_transaction.rb:46:in run' lib/gitlab/metrics/rack_middleware.rb:16:in call’
lib/gitlab/middleware/go.rb:21:in call' lib/gitlab/middleware/query_analyzer.rb:11:in block in call’
lib/gitlab/database/query_analyzer.rb:83:in within' lib/gitlab/middleware/query_analyzer.rb:11:in call’
lib/ci/job_token/middleware.rb:11:in call' batch-loader (2.0.5) lib/batch_loader/middleware.rb:11:in call’
rack-attack (6.7.0) lib/rack/attack.rb:103:in call' apollo_upload_server (2.1.6) lib/apollo_upload_server/middleware.rb:19:in call’
lib/gitlab/middleware/multipart.rb:173:in call' rack-attack (6.7.0) lib/rack/attack.rb:127:in call’
warden (1.2.9) lib/warden/manager.rb:36:in block in call' warden (1.2.9) lib/warden/manager.rb:34:in catch’
warden (1.2.9) lib/warden/manager.rb:34:in call' rack-cors (2.0.2) lib/rack/cors.rb:102:in call’
rack (2.2.10) lib/rack/tempfile_reaper.rb:15:in call' rack (2.2.10) lib/rack/etag.rb:27:in call’
rack (2.2.10) lib/rack/conditional_get.rb:27:in call' rack (2.2.10) lib/rack/head.rb:12:in call’
actionpack (7.0.8.6) lib/action_dispatch/http/permissions_policy.rb:38:in call' actionpack (7.0.8.6) lib/action_dispatch/http/content_security_policy.rb:36:in call’
lib/gitlab/middleware/read_only/controller.rb:50:in call' lib/gitlab/middleware/read_only.rb:18:in call’
lib/gitlab/middleware/unauthenticated_session_expiry.rb:18:in call' rack (2.2.10) lib/rack/session/abstract/id.rb:266:in context’
rack (2.2.10) lib/rack/session/abstract/id.rb:260:in call' actionpack (7.0.8.6) lib/action_dispatch/middleware/cookies.rb:704:in call’
lib/gitlab/middleware/same_site_cookies.rb:27:in call' actionpack (7.0.8.6) lib/action_dispatch/middleware/callbacks.rb:27:in block in call’
activesupport (7.0.8.6) lib/active_support/callbacks.rb:99:in run_callbacks' actionpack (7.0.8.6) lib/action_dispatch/middleware/callbacks.rb:26:in call’
sentry-rails (5.21.0) lib/sentry/rails/rescued_exception_interceptor.rb:14:in call' actionpack (7.0.8.6) lib/action_dispatch/middleware/debug_exceptions.rb:28:in call’
lib/gitlab/middleware/path_traversal_check.rb:35:in call' lib/gitlab/middleware/handle_malformed_strings.rb:21:in call’
sentry-ruby (5.21.0) lib/sentry/rack/capture_exceptions.rb:30:in block (2 levels) in call' sentry-ruby (5.21.0) lib/sentry/hub.rb:265:in with_session_tracking’
sentry-ruby (5.21.0) lib/sentry-ruby.rb:412:in with_session_tracking' sentry-ruby (5.21.0) lib/sentry/rack/capture_exceptions.rb:21:in block in call’
sentry-ruby (5.21.0) lib/sentry/hub.rb:59:in with_scope' sentry-ruby (5.21.0) lib/sentry-ruby.rb:392:in with_scope’
sentry-ruby (5.21.0) lib/sentry/rack/capture_exceptions.rb:20:in call' actionpack (7.0.8.6) lib/action_dispatch/middleware/show_exceptions.rb:29:in call’
lib/gitlab/middleware/basic_health_check.rb:25:in call' lograge (0.11.2) lib/lograge/rails_ext/rack/logger.rb:15:in call_app’
railties (7.0.8.6) lib/rails/rack/logger.rb:25:in block in call' activesupport (7.0.8.6) lib/active_support/tagged_logging.rb:99:in block in tagged’
activesupport (7.0.8.6) lib/active_support/tagged_logging.rb:37:in tagged' activesupport (7.0.8.6) lib/active_support/tagged_logging.rb:99:in tagged’
railties (7.0.8.6) lib/rails/rack/logger.rb:25:in call' actionpack (7.0.8.6) lib/action_dispatch/middleware/remote_ip.rb:93:in call’
lib/gitlab/middleware/handle_ip_spoof_attack_error.rb:25:in call' lib/gitlab/middleware/request_context.rb:15:in call’
lib/gitlab/middleware/webhook_recursion_detection.rb:15:in call' request_store (1.5.1) lib/request_store/middleware.rb:19:in call’
rack (2.2.10) lib/rack/method_override.rb:24:in call' rack (2.2.10) lib/rack/runtime.rb:22:in call’
rack-timeout (0.7.0) lib/rack/timeout/core.rb:154:in block in call' rack-timeout (0.7.0) lib/rack/timeout/support/timeout.rb:19:in timeout’
rack-timeout (0.7.0) lib/rack/timeout/core.rb:153:in call' config/initializers/fix_local_cache_middleware.rb:11:in call’
lib/gitlab/middleware/compressed_json.rb:44:in call' actionpack (7.0.8.6) lib/action_dispatch/middleware/executor.rb:14:in call’
lib/gitlab/middleware/rack_multipart_tempfile_factory.rb:19:in call' rack (2.2.10) lib/rack/sendfile.rb:110:in call’
lib/gitlab/middleware/sidekiq_web_static.rb:20:in call' lib/gitlab/metrics/requests_rack_middleware.rb:79:in call’
gitlab-labkit (0.37.0) lib/labkit/middleware/rack.rb:22:in block in call' gitlab-labkit (0.37.0) lib/labkit/context.rb:35:in with_context’
gitlab-labkit (0.37.0) lib/labkit/middleware/rack.rb:21:in call' actionpack (7.0.8.6) lib/action_dispatch/middleware/request_id.rb:26:in call’
actionpack (7.0.8.6) lib/action_dispatch/middleware/host_authorization.rb:131:in call' railties (7.0.8.6) lib/rails/engine.rb:530:in call’
railties (7.0.8.6) lib/rails/railtie.rb:226:in public_send' railties (7.0.8.6) lib/rails/railtie.rb:226:in method_missing’
lib/gitlab/middleware/release_env.rb:12:in call' rack (2.2.10) lib/rack/urlmap.rb:74:in block in call’
rack (2.2.10) lib/rack/urlmap.rb:58:in each' rack (2.2.10) lib/rack/urlmap.rb:58:in call’
puma (6.5.0) lib/puma/configuration.rb:279:in call' puma (6.5.0) lib/puma/request.rb:99:in block in handle_request’
puma (6.5.0) lib/puma/thread_pool.rb:389:in with_force_shutdown' puma (6.5.0) lib/puma/request.rb:98:in handle_request’
puma (6.5.0) lib/puma/server.rb:468:in process_client' puma (6.5.0) lib/puma/server.rb:249:in block in run’
puma (6.5.0) lib/puma/thread_pool.rb:166:in `block in spawn_thread’

==> /var/log/gitlab/gitlab-workhorse/current <==
{“backend_id”:“rails”,“content_type”:“text/html; charset=utf-8”,“correlation_id”:“01JGM5Z04HD1DSSG0YQ2AYP32C”,“duration_ms”:475,“host”:“redacted.mil”,“level”:“info”,“method”:“GET”,
“msg”:“access”,“proto”:“HTTP/1.1”,“referrer”:“https://redacted.mil/“,“remote_addr”:“127.0.0.1:0”,“remote_ip”:“127.0.0.1”,“route”:”^/-/",“route_id”:“dash”,“status”:500,“system”:"htt
p”,“time”:“2025-01-02T13:55:35-05:00”,“ttfb_ms”:475,“uri”:“/-/smartcard/verify_certificate?client_certificate=(redacted base64 cert info)=ldapmain”,“user_agent”:“Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0”,“written_bytes”:1624}

==> /var/log/gitlab/nginx/gitlab_access.log <==
10.180.42.114 - - [02/Jan/2025:13:55:35 -0500] “GET /-/smartcard/verify_certificate?client_certificate=(redacted base64 cert info=ldapmain HTTP/2.0” 500 1624 “https://redacted.mil/” “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0” -
`

Web Page

Details

In our enterprise we use smartcards to login to our machines, websties, and access to our buildings. We have about 50 users with our instance. I have set my instance to use smartcards in my gitlab.rb:
'### Smartcard authentication settings
###! Docs: Smart card authentication | GitLab
gitlab_rails[‘smartcard_enabled’] = true
gitlab_rails[‘smartcard_ca_file’] = “/etc/gitlab/trusted-certs/tls-ca-bundle.pem”
#gitlab_rails[‘smartcard_client_certificate_required_host’] = ‘redacted.mil’
#gitlab_rails[‘smartcard_client_certificate_required_port’] = 3444
gitlab_rails[‘smartcard_required_for_git_access’] = true
gitlab_rails[‘smartcard_san_extensions’] = true

Manual LDAP query with rails seems to work
'irb(main):002:0> Rails.logger.level = Logger::DEBUG
=> 0
irb(main):003:0> adapter = Gitlab::Auth::Ldap::Adapter.new(‘ldapmain’) # If main is the L
DAP provider
=>
#<Gitlab::Auth::Ldap::Adapter:0x00007fca205e6ae0
irb(main):005:0> Gitlab::Auth::Ldap::Person.find_by_uid(‘redacted.user’, adapter)
=>
#<Gitlab::Auth::Ldap::Person:0x00007fca21a9a900
@entry=
#<Net::LDAP::Entry:0x00007fca21a9cbd8
@myhash=
{:dn=>
[“CN=Redacted M. User -CTR,OU=Place,OU=Place,OU=Place,OU=Place,DC=Place,DC=Place,DC=MIL”],
:sn=>[“User”],
:givenname=>[“Redacted”],
:displayname=>[“Redacted. User - CTR”],
:memberof=>
Lots of membership information,
:samaccountname=>[“Redacted M. User”],
:mail=>[“redacted.user@.mil”]}>,
@provider=“ldapmain”>

Our smartcards are provided to us and cannot change the contents on them. I have been trying to match based on principal name because in the SAN of our certs is the PN (pricipalName) which is would DoD ID. This is how active directory finds us in the directory. I have tried using other ways to match and find the users in active directory but without success.