{"id":37046501,"url":"https://github.com/mdsol/mauth-client-dotnet","last_synced_at":"2026-01-14T05:29:39.250Z","repository":{"id":46289280,"uuid":"64276970","full_name":"mdsol/mauth-client-dotnet","owner":"mdsol","description":"Medidata.MAuth is a framework that provides support for authenticating web services and applications with the Medidata HMAC protocol, MAuth.","archived":false,"fork":false,"pushed_at":"2025-02-21T16:03:27.000Z","size":438,"stargazers_count":6,"open_issues_count":4,"forks_count":6,"subscribers_count":227,"default_branch":"develop","last_synced_at":"2025-11-27T13:37:59.325Z","etag":null,"topics":["study-conduct"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mdsol.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2016-07-27T04:26:26.000Z","updated_at":"2025-01-29T15:11:31.000Z","dependencies_parsed_at":"2024-02-20T23:28:33.233Z","dependency_job_id":"ea551489-3351-4203-8c57-948baaa04345","html_url":"https://github.com/mdsol/mauth-client-dotnet","commit_stats":{"total_commits":227,"total_committers":12,"mean_commits":"18.916666666666668","dds":0.5903083700440528,"last_synced_commit":"c6cdecc6e3bc3a19a8608caf7d41c2c139da981b"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/mdsol/mauth-client-dotnet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsol%2Fmauth-client-dotnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsol%2Fmauth-client-dotnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsol%2Fmauth-client-dotnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsol%2Fmauth-client-dotnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdsol","download_url":"https://codeload.github.com/mdsol/mauth-client-dotnet/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsol%2Fmauth-client-dotnet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28410494,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["study-conduct"],"created_at":"2026-01-14T05:29:38.606Z","updated_at":"2026-01-14T05:29:39.242Z","avatar_url":"https://github.com/mdsol.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Medidata.MAuth\n\nMedidata.MAuth is a framework that provides support for authenticating web services and applications\nwith the Medidata HMAC protocol, MAuth.\n\n## What is MAuth?\n\nThe MAuth protocol provides a fault-tolerant, service-to-service authentication scheme for Medidata and third-party\napplications that use web services to communicate. The Authentication Service and integrity algorithm is based on\ndigital signatures encrypted and decrypted with a private/public key pair.\n\nThe Authentication Service has two responsibilities. It provides message integrity and provenance validation by\nverifying a message sender's signature; its other task is to manage public keys. Each public key is associated with\nan application and is used to authenticate message signatures. The private key corresponding to the public key in the\nAuthentication Service is stored by the application making a signed request; the request is encrypted with this\nprivate key. The Authentication Service has no knowledge of the application's private key, only its public key.\n\n## Medidata.MAuth Components\n\nThe framework is divided into separate semi-dependent NuGet packages to provide only the functionality which you need\nin your application. Below you can find the description of each individual packages.\n\n### Medidata.MAuth.Core\n\nA core package for the MAuth protocol. This package contains the core functionality which used by the other MAuth\nauthentication protocol-specific components. This package also can be used standalone if you want to sign HTTP/HTTPS\nrequests with Medidata MAuth keys using the .NET _HttpClient_ message handler mechanism.\n\nThe package recommended in client applications where the application is required to issue MAuth-signed requests to an\nMAuth-enabled service.\n\n### Medidata.MAuth.Owin\n\nThis package contains an OWIN middleware to validate signed HTTP requests with the Medidata MAuth protocol.\nThe middleware communicates with an MAuth server in order to confirm the validity of the request authentication header.\n\nInclude this package in your OWIN-enabled application if you want to authenticate the incoming requests signed with\nthe MAuth protocol.\n\n### Medidata.MAuth.AspNetCore\n\nSimilar to the [Owin package](#Medidata-MAuth-Owin) this package has the ASP.NET Core-specific middleware that\nvalidates signed HTTP requests incoming to the application.\n\nYou can add this package in your ASP.NET Core web api application if you would like to authenticate your incoming\nrequests signed with the MAuth protocol.\n\n### Medidata.MAuth.WebApi\n\nThe package contains an HTTP message handler to validate signed HTTP requests with the Medidata MAuth protocol.\nThe handler communicates with an MAuth server in order to confirm the validity of the request authentication header.\n\nInclude this package in your WebAPI application if you want to authenticate the incoming requests signed with\nthe MAuth protocol.\n\n## Get Started\n\nBelow you can find some information and examples on getting started using the framework.\n\n### Installation\n\nDepending on your needs you can install either the Core package only (for signing requests), or the Owin or WebApi\npackages as well if you want to authenticate incoming requests.\n\nThe installation is as usual with NuGet.\n\nFor signing:\n\n```\nnuget install Medidata.MAuth.Core\n```\n\nOr in case of the authenticating, either\n\n```\nnuget install Medidata.MAuth.Owin\n```\n\nor\n\n```\nnuget install Medidata.MAuth.WebApi\n```\n\nFor all of these you can use the _Visual Studio Package Manager_ as well.\n\nThe Owin, AspNetCore and WebApi packages are dependent on the Core package, therefore it will be installed automatically in those\ncases.\n\n### Signing Outgoing Requests\n\nIn order to sign outgoing requests, an `MAuthSigningHandler` class is provided in the Core package. This handler\naccepts an `MAuthSigningOptions` instance which stores all the necessary settings for the signing process.\n\nAn example:\n\n```C#\nusing Medidata.MAuth.Core;\nusing Medidata.MAuth.Core.Models;\n\npublic async Task\u003cHttpResponseMessage\u003e SignAndSendRequest(HttpRequestMessage request)\n{\n    var signingHandler = new MAuthSigningHandler(new MAuthSigningOptions()\n    {\n        ApplicationUuid = new Guid(\"7c872d75-986b-4c61-bb17-f2569d42bfb0\"),\n\n        // The following can be either a path to the key file or the contents of the file itself\n        PrivateKey = \"ClientPrivateKey.pem\",\n\n        // Enumerations of signing protocols, if not provided defaults to `MAuthVersion.MWS`for sign-in.\n        SignVersions = MAuthVersion.MWS | MAuthVersion.MWSV2\n    });\n\n    using (var client = new HttpClient(signingHandler))\n    {\n        return await client.SendAsync(request);\n    }\n}\n```\n\nThe `SignVersions` parameter can be used to specify which protocol version to sign outgoing requests with:\n- `SignVersions = MAuthVersion.MWS`: signs with the `MWS` protocol only.\n- `SignVersions = MAuthVersion.MWS | MAuthVersion.MWSV2` : signs with both the `MWS` and the `MWSV2` protocol.\nIf not supplied, it signs with the `MWS` protocol by default.\n\nSigning with `MWSV2` protocol supports query string.\n\nThe example above is creating a new instance of a `HttpClient` with the handler responsible for signing the\nrequests and sends the request to its designation. Finally it returns the response from the remote server.\n\nThe `MAuthSigningOptions` has the following properties to determine the required settings:\n\n| Name | Description |\n| ---- | ----------- |\n| **ApplicationUuid** | Determines the unique identifier of the client application used for the MAuth service authentication requests.  This uuid needs to be registered with the MAuth Server in order for the authenticating server application to be able to authenticate the signed request. |\n| **PrivateKey** | Determines the RSA private key of the client for signing a request. This key must be in a PEM ASN.1 format. The value of this property can be set as a valid path to a readable key file as well. |\n| **SignVersions** | (optional) Enumerations of MAuth protocol versions to sign requests. If not supplied, defaults to `MWS`.\n\n### Authenticating Incoming Requests with the OWIN and ASP.NET Core Middlewares\n\nIf your application implements the OWIN-specific or ASP.NET Core pipeline, you can wire in the `MAuthMiddleware`\nprovided by the Owin and AspNetCore NuGet packages.\n\nThe setting and usage is as follows in case of OWIN (in the application's `Startup` class):\n\nWith the update of MAuth V2 protocol, the authentication will first check for mauth header with `MWSV2` and if not found then only fallback to authenticate for `MWS` version.\nAlso, there is options of `DisableV1`, which is `false` by default and when we are ready to disable authentication of V1 protocl i.e. `MWS` version, then we need to pass this option too as `true`.\n\n```C#\nusing Medidata.MAuth.Owin;\n\npublic class Startup\n{\n    public void Configuration(IAppBuilder app)\n    {\n        app.UseMAuthAuthentication(options =\u003e\n        {\n            options.ApplicationUuid = new Guid(\"a419de8f-d759-4db9-b9a7-c2cd14174987\");\n            options.MAuthServiceUrl = new Uri(\"https://mauth.imedidata.com\");\n            options.AuthenticateRequestTimeoutSeconds = 3;\n            options.MAuthServiceRetryPolicy = MAuthServiceRetryPolicy.RetryOnce;\n            options.HideExceptionsAndReturnUnauthorized = true;\n            options.PrivateKey = \"ServerPrivateKey.pem\";\n            options.Bypass = (request) =\u003e request.Uri.AbsolutePath.StartsWith(\"/allowed\");\n\n            // when ready to disable authentication of V1 protococl\n            options.DisableV1 = true;\n        });\n    }\n}\n```\nFor enabling the logging from Owin application, the following configuration will need to be added or updated:\n```C#\n\u003cconfiguration\u003e\n  \u003csystem.diagnostics\u003e\n    \u003cswitches\u003e\n      \u003cadd name=\"Microsoft.Owin\" value=\"Information, Error, Warning\" /\u003e\n    \u003c/switches\u003e\n  \u003c/system.diagnostics\u003e\n\u003c/configuration\u003e\n```\n\nA similar way can be implemented for ASP.NET Core (also in the `Startup` class):\n\n```C#\nusing Medidata.MAuth.AspNetCore;\n\npublic class Startup\n{\n    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)\n    {\n        app.UseMAuthAuthentication(options =\u003e\n        {\n            options.ApplicationUuid = new Guid(\"a419de8f-d759-4db9-b9a7-c2cd14174987\");\n            options.MAuthServiceUrl = new Uri(\"https://mauth.imedidata.com\");\n            options.AuthenticateRequestTimeoutSeconds = 3;\n            options.MAuthServiceRetryPolicy = MAuthServiceRetryPolicy.RetryOnce;\n            options.HideExceptionsAndReturnUnauthorized = true;\n            options.PrivateKey = \"ServerPrivateKey.pem\";\n            options.Bypass = (request) =\u003e request.Uri.AbsolutePath.StartsWith(\"/allowed\");\n\n            // when ready to disable authentication of V1 protococl\n            options.DisableV1 = true;\n        });\n    }\n}\n```\n\nThe middlewares take an `MAuthMiddlewareOptions` instance to set up the authentication:\n\n| Name | Description |\n| ---- | ----------- |\n| **ApplicationUuid** | Determines the unique identifier of the server application used for the MAuth service authentication requests. This uuid needs to be registered with the MAuth Server in order to use it. |\n| **MAuthServiceUrl** | Determines the endpoint of the MAuth authentication service. This endpoint is used by the authentication process to verify the validity of the signed request. |\n| **PrivateKey** | Determines the RSA private key of the server application for the authentication requests. This key must be in a PEM ASN.1 format. The value of this property can be set as a valid path to a readable key file as well. |\n| **AuthenticateRequestTimeoutSeconds** | An optional parameter that determines the timeout in seconds for the MAuth authentication request - the MAuth component will try to reach the MAuth server for this duration before it throws an exception. If not specified, the default value will be **3 seconds**. |\n| **MAuthServiceRetryPolicy** | The policy for the retry attempts when communicating with the MAuth service. The following policies can be used: `NoRetry` (no retries), `RetryOnce` (one additional attempt), `RetryTwice` (two additional attempts) and `Agressive` (9 additional attempts) - the default value is **RetryOnce**. |\n| **HideExceptionsAndReturnUnauthorized** | An optional parameter that determines if the middleware should swallow all exceptions and return an empty HTTP response with a status code Unauthorized (401) in case of any errors (including authentication and validation errors). The default is **true**. |\n| **Bypass** | Determines a function which evaluates if a given request should bypass the MAuth authentication. |\n| **DisableV1** | Determines the boolean value which controls whether to disable the signing requests with `MAuthVersion.MWS` requests or not. If not supplied, this default value is  `false`. |\n\nThe **HideExceptionsAndReturnUnauthorized** parameter is useful (if set to **false**) when you have an exception handler\nmechanism (for example a logger) in your middleware pipeline. In this case the MAuth middleware won't swallow the\nexceptions but will throw them with full stack trace and details of the problem - as every authentication errors will\nthrow a `Medidata.MAuth.Core.AuthenticationException` you can still return a Unauthorized (401) HTTP status code in\nthose cases.\nIn the other hand, if you don't use any exception handling mechanism, it is recommended to leave this feature disabled\nas setting this to **false** can possibly lead to exposing sensitive details about your application and the\nauthentication process. Leaving this parameter as **true** will result the middleware to return a Unauthorized (401) HTTP\nstatus code for every error without showing any details.\n\nThe **Bypass** function takes a `IOwinRequest` in case of OWIN and an `HttpRequest` instance for ASP.NET Core and\nshould produce **true** as a result, if the given request satisfies the conditions to bypass the authentication;\notherwise it should result **false** therefore an authentication attempt will occur. If no Bypass predicate provided\nin the options, every request will be authenticated by default.\n\nWhen authentication of V1 requests needs to be disabled, then **DisableV1** should be passed as **true**.\n\n### Authenticating Incoming Requests with the WebApi Message Handler\n\nIf your application does not use the OWIN or ASP.NET Core middleware infrastructure, but it uses the ASP.NET WebAPI\nframework, the WebApi package provides an `MAuthAuthenticatingHandler` which can be assigned to WebAPI routes or\nthe global handler collection in order to automatically authenticate incoming requests.\n\nFor a global registration (that is, use MAuth authentication for all requests), you can register the handler as below\n(in your `WebApiConfig` class):\n\n```C#\nusing Medidata.MAuth.WebApi;\n\npublic static class WebApiConfig\n{\n    public static void Register(HttpConfiguration config)\n    {\n        var options = new MAuthWebApiOptions()\n        {\n            ApplicationUuid = new Guid(\"a419de8f-d759-4db9-b9a7-c2cd14174987\"),\n            MAuthServiceUrl = new Uri(\"https://mauth.imedidata.com\"),\n            AuthenticateRequestTimeoutSeconds = 3,\n            MAuthServiceRetryPolicy = MAuthServiceRetryPolicy.RetryOnce,\n            HideExceptionsAndReturnUnauthorized = true,\n            PrivateKey = \"ServerPrivateKey.pem\",\n\n            // when ready to disable authentication of V1 protococl\n            options.DisableV1 = true\n\n            // if loggerfactory is present\n            options.loggerfactory = new Microsoft.Extensions.Logging.LoggerFactory(); // or provide the existing loggerfactory\n        };\n\n        config.MessageHandlers.Add(new MAuthAuthenticatingHandler(options));\n    }\n}\n```\n\nAlternatively, you can add the authenticating handler to a specific route when you define the route:\n\n```C#\nusing Medidata.MAuth.WebApi;\n\npublic static class WebApiConfig\n{\n    public static void Register(HttpConfiguration config)\n    {\n        var options = // See the previous example\n\n        config.Routes.MapHttpRoute(\n            name: \"Route1\",\n            routeTemplate: \"api/{controller}/{id}\",\n            defaults: new { id = RouteParameter.Optional },\n            constraints: null,\n            handler: new MAuthAuthenticatingHandler(options)\n        );\n    }\n}\n```\n\nIn the examples above, the `MAuthWebApiOptions` instance has the same properties as the OWIN- and\nASP.NET Core-specific `MAuthMiddlewareOptions`.\n\n## Frequently Asked Questions\n\n##### What are the license terms for Medidata.MAuth?\n\nThe framework is licensed under the [MIT licensing terms](https://github.com/mdsol/mauth-client-dotnet/blob/master/LICENSE.md).\n\n##### What is the current target .NET Framework version?\n\nThe current target is **.NET Framework 4.6.1** - this means that you have to use at least this target framework version\nin your project in order to make Medidata.MAuth work for you.\n\n##### Is there an .NET Standard/Core support?\n\nYes, for signing outgoing requests you can use the library with any framework which implements\nthe **.NET Standard 2.0** and onwards; additionally we support the **ASP.NET Core App 2.1** and onwards with a middleware\nfor authenticating the incoming requests.\n\n##### What Cryptographic provider is used for the encryption/decryption?\n\nIn the latest version of 4.0.0, we are using the available dotnet security [System.Security.Cryptography](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography?view=dotnet-plat-ext-3.1)\nwhich works for both **.NET Framework 4.6.1** and **.NET Standard 2.0** when using the V2 protocol.\nHowever, to also support the V1 protcol, we are still maintaining the BouncyCastle library as mentioned below.\n\nOn the .NET Framework side (WebAPI, Owin, Core) we are using the latest version (as of date 1.81) of the\n[BouncyCastle](https://github.com/bcgit/bc-csharp) library; on the .NET Standard side (Core, AspNetCore) we are using\nthe portable fork of the [BouncyCastle](https://github.com/onovotny/BouncyCastle-PCL) library.\n\n##### What are the major changes in the 5.0.0 version?\nIn this version we have removed the property `DisableV1` from `MAuthSigningOptions`. Instead, we have added new option as\n`SignVersions` in `MAuthSigningOptions` which takes enumeration values of MAuth protcol versions `MWS` and/ or `MWSV2` protocol.\nIf this option is not provided, then it will sign in by `MWS` protocol as default.\n\n##### What are the major changes in the 4.0.0 version?\n\nIn this version we have added support for V2 protocol which uses `MCC-Authentication` as MAuthHeader and  `MCC-Time` as\nMAuthTimeHeader. And, this V2 protocol supports for signing and authenticating url with query string parameters.\nFor Signing, we added two new options in `MAuthSigningOptions`: `MAuthVersion` which is mandatory and takes enumeration\n value of `MAuthVersion.MWSV2` for V2 protocol or `MAuthVersion.MWS` for continue of using V1 protocol.\nAnother option `DisableV1` is `false` by default if not provided. But, it is needed to provide as `true` when the client\nneed to sign on by no more supporting V1 protocol.\n\nAlso while authentication, the logic defaults to check for V2 protcol header `MWSV2` and if fails then only fallback to\ncheck for V1 protocol header for `MWS`. Also, `MAuthOptionsBase` includes new option as `DisableV1` which is `false` by\ndefault and need to be passed as `true` if the authenticating client no longer wants to support V1 protocol.\n\n##### What are the major changes in the 2.0.0 version?\n\nIn this version we have only one major and a minor change: from this version the `MAuthSigningHandler` is accepting an\n`MAuthSigningOptions` instance instead of an `MAuthOptions` instance (which in turn set to be an abstract class).\nThis change was necessary because the MAuthOptions object contains the `MAuthServiceUrl` property, which is not required\nfor signing, but it had to be set to a valid Url nonetheless.\n\nThe other underlying change is that in the OWIN middleware the infrastructure provided request body stream gets replaced\nwith a `MemoryStream` in cases when the original body stream is not seekable. This change was necessary, because in\norder to authenticate the request we need to read the body, but if the body stream is not seekable we are not able to\nrestore it for the subsequent middlewares to read. Typical example for this is when the OWIN selfhost infrastructure\nis used as it wraps the original stream in a non-seekable version.\n\n##### Does Medidata.MAuth support caching?\n\nYes, all the **ASP.NET WebApi** handler and the **Owin** and **ASP.NET Core** middlewares support caching of the `ApplicationInfo` from the MAuth server in\norder to not overload it with client information requests (and gradually improve the response times from the middlewares).\nThe cache expiration will be set according to the response cache header (max-age) from the MAuth server - or if this\ninformation not provided, it will be **1 hour** by default for successful requests (i.e. valid application uuids).\n\n##### The documentation for the `MAuthServiceRetryPolicy.Agressive` retry policy says that it is not recommended for production use. What is the reason for this?\n\nThis policy will make the number of requests to the MAuth service to an overall 10 attempts. We believe that the chance\nto receive a successful response from the MAuth service is gradually decreasing by the number of attempts (the more\nthe clients are sending requests to a presumably overloaded server the less the chance for a successful response) -\ntherefore we do not recommend to use this policy in any production scenario.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdsol%2Fmauth-client-dotnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdsol%2Fmauth-client-dotnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdsol%2Fmauth-client-dotnet/lists"}