ARTIFACTORY: Using mTLS certificates for user authorization in Artifactory

ARTIFACTORY: Using mTLS certificates for user authorization in Artifactory

Products
Frog_Artifactory
Content Type
Administration_Platform
AuthorFullName__c
Maxim Sidorovich
articleNumber
000006513
FirstPublishedDate
2025-07-07T12:20:48Z
lastModifiedDate
2025-07-07
Introduction 

JFrog Platform offers multiple authentication options such as SSO, SCIM and LDAP. In this article, we will focus on using mTLS as an authentication method. 
mTLS (Mutual TLS) is an enhanced form of TLS in which both client and server exchange and validate X.509 certificates during the handshake, so each side proves its identity before the encrypted session begins. 

This article will cover the steps to enable mTLS for Artifactory reverse proxied by Nginx, as per this user guide in order to achieve the authentication flow as below:

User-added image 

Creating an mTLS certificate: 

1. Create the CA’s private key:
openssl genrsa -out mtls-ca.key 4096
2. Generate a self-signed CA certificate:
openssl req -x509 -new -nodes  -key mtls-ca.key -sha256 -days 3650 -subj "/C=US/ST=State/L=City/O=YourOrg/OU=YourUnit/CN=Artifactory-users" -out mtls-ca.crt
3. Create the client’s private key:
openssl genrsa -out mtls-client.key 2048
4. Create a client CSR:
openssl req -new -key mtls-client.key -subj "/C=US/ST=State/L=City/O=YourOrg/OU=Client/CN=test" -out mtls-client.csr
5. Sign the client CSR with your CA:
openssl x509 -req -in mtls-client.csr -CA mtls-ca.crt -CAkey mtls-ca.key -sha256 -days 365 -out mtls-client.crt
6. (Optional) Bundle client key + cert into a single file
cat mtls-client.key mtls-client.crt > mtls-client.pem
7. (Optional) Verify certificates:
openssl verify -CAfile mtls-ca.crt mtls-client.crt
Nginx configuration  

On Nginx side we have three important directives that can be configured:

ssl_verify_client - controls the handshake behaviour
  • ssl_verify_client on - every request should be authorized with mtls (optional)
  • ssl_verify_client optional - a request may be or may be not authorized with mtls (recomended)
  • ssl_verify_client optional_no_ca - any mTLS certificate (not signed by the CA) will be authorized (strongly avoided). 
ssl_verify_depth - controls the certificate-chain depth.
  • ssl_verify_depth 2 - verifies the certificate using this chain:  Root CA (depth 0) → Intermediate CA (1) →
  • Client cert (2). The depth can be shorter than the value set. 
    If the client supplies a chain longer than this value, the handshake fails with 400 Certificate Chain Too Long.
proxy_set_header X-JFrog-Client-Cert "" - defines the header title. Can be replaced with a custom header (a corresponding change in access.config.yml is required)

Artifactory configuration  

In order to enable the mTLS in artifactory, please modify access.config.yml while keeping in mind the following options:
  • Header-name: X-JFrog-Client-Cert   - name of the HTTP header that contains the client certificate, the same as the HTTP header name set in Nginx
  • Cache-expiry-secs: 100  - period in seconds during which a successful mTLS authentication should be considered valid
  • Extraction-regex: (.*)  - regular expression used to extract the username from the certificate's subject CN. For example, setting it to [^@]+(?=\d{0,}@) will allow username extraction when the certificate for user “test” is issued for a CN=test@myorg.com
  • No-auto-create-users: false - avoid automatic creation of users in the system if they do not exist. If set to true, no user will be created, if a certificate is issued for a non-existent user.
  • Allow-user-to-access-profile: false - allow created users (based on the flag above) access their profile page in the UI
  • Sync-ldap-groups: false - automatically associate the authenticated user with groups returned from LDAP    
Testing an mTLS authentication

Once the settings above are active, we can test our setup by deploying a sample artifact.
In order to proceed, in Artifactory, we have created a valid user “test”, with appropriate permissions and a corresponding certificate. We have also created a certificate for user “test11” which is not registered in Artifactory, effectively making him an invalid user.

Valid user request and response:
curl --cert client.pem -T ./test.artifact "https://myart:443/artifactory/example-repo-local/test" --insecure

{
  "repo" : "example-repo-local",
  "path" : "/test",
  "created" : "2025-07-06T11:36:58.845Z",
  "createdBy" : "test",
  "downloadUri" : "https://myart:443/artifactory/example-repo-local/test",
  "mimeType" : "application/octet-stream",
  "size" : "3262",
  "checksums" : {
    "sha1" : "99b2e37e00b8615c1209baeee24c5556f7c796d8",
    "md5" : "3f42721552ee33cae0e12af63a640fb8",
    "sha256" : "d2d5718133c2c66b7cd78bb63e72af9ee5b5f0515633430b84b0f6f5b874fee6"
  },
  "originalChecksums" : {
    "sha256" : "d2d5718133c2c66b7cd78bb63e72af9ee5b5f0515633430b84b0f6f5b874fee6"
  },
  "uri" : "https://myart:443/artifactory/example-repo-local/test"
}%  
In artifactory-request.log:
2025-07-06T11:50:13.418Z|605d6a0735865247|8.8.8.8|test|PUT|/example-repo-local/test|201|3262|0|44|curl/8.7.1
Invalid user request and response:
curl --cert client1.pem -T ./test.artifact "https://myart:443/artifactory/example-repo-local/test" --insecure

{
  "errors" : [ {
    "status" : 403,
    "message" : "User test11 is not permitted to deploy 'test' into 'example-repo-local:test'."
  } ]
}%
In artifactory-request.log:
2025-07-06T11:51:46.328Z|1b3c5eba0ffac66d|8.8.8.8|test11|PUT|/example-repo-local/test|403|3262|0|52|curl/8.7.1