Open Closed

Use authMechanism=MONGODB-X509 #8930


User avatar
0
g.maldarelli created
  • ABP Framework version: v9.0.4

  • UI Type: Blazor WASM

  • Database System: MongoDB

  • Tiered (for MVC) or Auth Server Separated (for Angular): yes/no

  • Exception message and full stack trace:

  • Steps to reproduce the issue:

I don't find a way to connect into my mongo atlas cluster using a authMechanism=MONGODB-X509 like in this example with standard MongoDB.Driver Version="2.30.0"

//.... var connectionString ="mongodb+srv://xx-mongo.xx.mongodb.net/xx-app-db?retryWrites=true&w=majority&appName=xx-mongo&tls=true&authMechanism=MONGODB-X509"; var settings = MongoClientSettings.FromConnectionString(connectionString); settings.ServerApi = new ServerApi(ServerApiVersion.V1); var cert = new X509Certificate2("atlas-user-cert.pfx","changeit"); settings.SslSettings = new SslSettings { ClientCertificates = new List<X509Certificate>() { cert } }; var client = new MongoClient(settings);
//......

Can you help me?

Thanks
Giuseppe


5 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you connect your MongoDB in another app/code?

    Do you have any example code of authMechanism=MONGODB-X509?

    Thanks.

  • User Avatar
    0
    g.maldarelli created

    Yes
    follow a console app that works fine whith the same cluster

    
    using MongoDB.Bson;
    using MongoDB.Driver;
    using System;
    using System.IO;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    using System.Security.Cryptography.X509Certificates;
    using System.Text.Json;
    using AtlasCertConnection;
    using AtlasCertConnection.Model.Report;
    using MongoDB.Driver.Linq;
    using TransitalyApp.Shipments;
    using AtlasCertConnection.Model.Types;
    using System.Linq;
    using AtlasCertConnection.Data;
    using AtlasCertConnection.Model;
    using MongoDB.Bson.Serialization;
    
    class Program
    {
        static void Main(string[] args)
        {
            BsonSerializer.RegisterSerializationProvider( new CustomTypeSerializationProvider());
            MainAsync().Wait();
        }
    
        static async Task MainAsync()
        {
            var connectionString =
                "mongodb+srv://ibl-mongo.dizxt.mongodb.net/tri-app-db?retryWrites=true&w=majority&appName=ibl-mongo&tls=true&authMechanism=MONGODB-X509&authSource=%24external";
            var settings = MongoClientSettings.FromConnectionString(connectionString);
            settings.ServerApi = new ServerApi(ServerApiVersion.V1);
    
            var cert = new X509Certificate2(
                "C:\\projects\\development\\IBL\\Trabsitaly\\TransitalyApp\\src\\TransitalyApp.HttpApi.Host\\atlas-user-cert.pfx",
                "changeit");
    
            settings.SslSettings = new SslSettings
            {
                ClientCertificates = new List<X509Certificate>() { cert }
            };
    
            var client = new MongoClient(settings);
            var database = client.GetDatabase("tri-app-db");
            var collection = database.GetCollection<Shipment>("AppShipments");
            var deliveryMinDateThreshold = new DateTime(2025, 3, 1);
            var deliveryMaxDateThreshold = new DateTime(2026, 3, 1);
            var result = collection.Aggregate<Shipment>()
                .Match(Builders<Shipment>.Filter.And(
                    Builders<Shipment>.Filter.Eq("Status", "DELIVERED"),
                    Builders<Shipment>.Filter.Gte("DeliveryExecutedDate", deliveryMinDateThreshold),
                    Builders<Shipment>.Filter.Lte("DeliveryExecutedDate", deliveryMaxDateThreshold)
                ))
                .Sort(new BsonDocument("CreationTime desc", 1))
                .Skip(0)
                .Limit(2000).ToList() ?? [];
    
            Console.WriteLine(result.Count);
            result = PatchNotifyRecipient(result);
            ShippingCostCalculator.GenerateReport(result);
    
    
    
    
        }
    
        private static List<Shipment> PatchNotifyRecipient(List<Shipment> result)
        {
            result.ForEach(shipment =>
            {
                if (shipment.AccessoryServices.FirstOrDefault(s => s.Type == AccessoryServiceType.NOTIFY_RECIPIENT) is null)
                {
                    shipment.AccessoryServices.Add(new AccessoryService
                    {
                        Type = AccessoryServiceType.NOTIFY_RECIPIENT,
                        Description = "Call"
                    });
                }
            });
            return result;
        }
    }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You can override the UnitOfWorkMongoDbContextProvider's CreateMongoClient method to change the code of creating MongoClient.

    Add YourUnitOfWorkMongoDbContextProvider : UnitOfWorkMongoDbContextProvider

    Then replace it in DI.

    context.Services.TryAddTransient(
        typeof(IMongoDbContextProvider<>),
        typeof(UnitOfWorkMongoDbContextProvider<>)
    );
    

    https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs#L300-L306

    var connectionString = "mongodb+srv://ibl-mongo.dizxt.mongodb.net/tri-app-db?retryWrites=true&w=majority&appName=ibl-mongo&tls=true&authMechanism=MONGODB-X509&authSource=%24external";
    var settings = MongoClientSettings.FromConnectionString(connectionString);
    settings.ServerApi = new ServerApi(ServerApiVersion.V1);
    
    var cert = new X509Certificate2("C:\\projects\\development\\IBL\\Trabsitaly\\TransitalyApp\\src\\TransitalyApp.HttpApi.Host\\atlas-user-cert.pfx", "changeit");
    
    settings.SslSettings = new SslSettings
    {
        ClientCertificates = new List<X509Certificate>() { cert }
    };
    
    var client = new MongoClient(settings);
    
  • User Avatar
    0
    g.maldarelli created

    the complete solution for future framework improvement:

    `using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    using MongoDB.Driver;
    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.OpenSsl;
    using Org.BouncyCastle.Security;
    using Volo.Abp.Data;
    using Volo.Abp.MongoDB;
    using Volo.Abp.MultiTenancy;
    using Volo.Abp.Threading;
    using Volo.Abp.Uow;
    using Volo.Abp.Uow.MongoDB;

    public class
    X509CertificateUnitOfWorkMongoDbContextProvider : UnitOfWorkMongoDbContextProvider
    where TMongoDbContext : IAbpMongoDbContext
    {
    private readonly IConfiguration _configuration;
    private X509Certificate2 _certificate;
    private String _certPassword;
    private bool useX509Certificate = false;

    public X509CertificateUnitOfWorkMongoDbContextProvider(IUnitOfWorkManager unitOfWorkManager,
        IConnectionStringResolver connectionStringResolver, ICancellationTokenProvider cancellationTokenProvider,
        ICurrentTenant currentTenant, IOptions options,
        IMongoDbContextTypeProvider dbContextTypeProvider, IConfiguration configuration) : base(unitOfWorkManager,
        connectionStringResolver,
        cancellationTokenProvider, currentTenant, options, dbContextTypeProvider)
    {
        _configuration = configuration;
        this.SetX509AuthenticationMechanism();
    }
    
    private void SetX509AuthenticationMechanism()
    {
        var connectionString = _configuration["ConnectionStrings:Default"];
        if (connectionString is not null && connectionString.Contains("authMechanism=MONGODB-X509"))
        {
            useX509Certificate = true;
            this._certPassword = Guid.NewGuid().ToString();
            var certFilePath = _configuration["ConnectionStrings:X509Certificate:CertFile"];
            var keyFilePath = _configuration["ConnectionStrings:X509Certificate:KeyFile"];
            this._certificate = LoadCertificateFromPem(certFilePath, keyFilePath);
        }
    }
    
    protected override MongoClient CreateMongoClient(MongoUrl mongoUrl)
    {
        var mongoClientSettings = MongoClientSettings.FromUrl(mongoUrl);
        if (useX509Certificate)
        {
            try
            {
                mongoClientSettings.ServerApi = new ServerApi(ServerApiVersion.V1);
                mongoClientSettings.SslSettings = new SslSettings
                {
                    ClientCertificates = new List() { _certificate },
                };
                Options.MongoClientSettingsConfigurer?.Invoke(mongoClientSettings);
                return new MongoClient(mongoClientSettings);
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Error while creating MongoClient with X509 certificate");
                throw;
            }
        }
    
        return base.CreateMongoClient(mongoUrl);
    }
    
    
    /// 
    /// Load X509 certificate from PEM file
    /// 
    private X509Certificate2 LoadCertificateFromPem(string? pemFilePath, string? keyFilePath)
    {
        if (pemFilePath is null || keyFilePath is null || !File.Exists(pemFilePath) || !File.Exists(keyFilePath))
        {
            throw new FileNotFoundException($"PEM or Key file not found at {pemFilePath} or {keyFilePath}");
        }
    
        var certificate = X509Certificate2.CreateFromPemFile(pemFilePath, keyFilePath);
        return new X509Certificate2(certificate.Export(X509ContentType.Pfx, _certPassword), _certPassword);
    }
    

    }`

    to replace in a correct way the provider use this code:

    private void ConfigureMongoX509CertificateProvider(ServiceConfigurationContext context, IConfiguration configuration) { context.Services.Replace(ServiceDescriptor.Transient( typeof(IMongoDbContextProvider<>), typeof(X509CertificateUnitOfWorkMongoDbContextProvider<>))); }

    Thanks
    Giuseppe

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Many Thanks Giuseppe

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
Do you need assistance from an ABP expert?
Schedule a Meeting
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v9.2.0-preview. Updated on March 13, 2025, 04:08