Skip to content

fix: extract gitlab_realm from header instead of hardcoding to sm

Aleksei Lipniagov requested to merge alipniagov-fix-user-jwt-gitlab-realm-bug into main

What does this merge request do and why?

We should not hardcode the gitlab_realm value in the claim - it is a bug, probably because of the recent refactor. Instead, we extract it from the headers.

How to set up and validate locally

You need to run 2 requests to v1/code/user_access_token.

The first is for SM.
Run your local CDot, receive a token, then send:

curl --request POST \
  --url 'http://localhost:5052/v1/code/user_access_token' \
  --header 'Authorization: Bearer YOUR_TOKEN_FROM_CDOT' \
  --header 'X-Gitlab-Authentication-Type: oidc' \
  --header 'Content-Type: application/json' \
--header 'X-Gitlab-Global-User-Id: 111' \
--header 'X-Gitlab-Realm: self-managed' \
--header 'X-Gitlab-Instance-Id: 37402906-c038-408d-bdb7-77e9c5821dc9' \
--header 'Bypass-Auth: true'

Note 'X-Gitlab-Realm: self-managed'.
Decode the result in JWT.io and make sure "gitlab_realm": "self-managed".

For Gitlab.com (SaaS) scenario, you should self-issue a token from your instance (acting as GITLAB_SIMULATE_SAAS=1)

curl --request POST \
  --url 'http://localhost:5052/v1/code/user_access_token' \
  --header 'Authorization: Bearer YOUR_TOKEN_FROM_SAAS' \
  --header 'X-Gitlab-Authentication-Type: oidc' \
  --header 'Content-Type: application/json' \
--header 'X-Gitlab-Global-User-Id: 111' \
--header 'X-Gitlab-Realm: saas' \
--header 'X-Gitlab-Instance-Id: 37402906-c038-408d-bdb7-77e9c5821dc9' \
--header 'Bypass-Auth: true'

Note 'X-Gitlab-Realm: saas'. Also note that if you simply change 'X-Gitlab-Realm: saas' in the previous curl and keep the same token you received from CDot, you will get {"error":"Header mismatch 'X-Gitlab-Realm'"}% because CDot only issues SM claims (see https://gitlab.com/gitlab-org/customers-gitlab-com/blob/993d348e51774b9485116d790f887d925c0bf19e/app/models/auth/json_web_token.rb#L43)

Decode the result in JWT.io and make sure "gitlab_realm": "saas".

Note:

I self-issued token via ::CloudConnector::AvailableServices.find_by_name(:code_suggestions).access_token(User.first)

I am running export GITLAB_SIMULATE_SAAS=1 && GITLAB_LICENSE_MODE=test && export CUSTOMER_PORTAL_URL='http://localhost:5000' && export CODE_SUGGESTIONS_BASE_URL='http://localhost:5052' && export AI_GATEWAY_URL=http://0.0.0.0:5052 && export LLM_DEBUG=1 && rails c.

I also needed to hack a code in CloudConnector::GitlabCom::AvailableServiceData:

      def access_token(resource = nil, extra_claims: {})
        ::Gitlab::CloudConnector::SelfIssuedToken.new(
          audience: backend,
          subject: Gitlab::CurrentSettings.uuid,
          scopes: ["code_suggestions"],
          extra_claims: extra_claims
        ).encoded
      end

I hardcoded scopes to ["code_suggestions"] as something was weird with my local add-ons (maybe they are only for SM?)

I double-checked the token issued from the rails console via jwt.io, and it was correct.

Merge request checklist

  • Tests added for new functionality. If not, please raise an issue to follow up.
  • Documentation added/updated, if needed.
Edited by Aleksei Lipniagov

Merge request reports