{"id":13879675,"url":"https://github.com/mdsol/mauth-client-ruby","last_synced_at":"2025-07-16T15:32:50.450Z","repository":{"id":10299677,"uuid":"64370006","full_name":"mdsol/mauth-client-ruby","owner":"mdsol","description":"Mauth client in Ruby","archived":false,"fork":false,"pushed_at":"2024-04-25T20:51:49.000Z","size":769,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":334,"default_branch":"master","last_synced_at":"2024-11-16T12:49:41.388Z","etag":null,"topics":["platform","product-quality","site-mgmt","study-conduct"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","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.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-07-28T06:33:22.000Z","updated_at":"2024-04-25T20:51:50.000Z","dependencies_parsed_at":"2024-01-13T20:57:40.734Z","dependency_job_id":"52679cf5-5db0-443e-b986-b97484310eed","html_url":"https://github.com/mdsol/mauth-client-ruby","commit_stats":{"total_commits":636,"total_committers":24,"mean_commits":26.5,"dds":0.6839622641509434,"last_synced_commit":"7975d2d5370e58ada7996ae6548bbbde081dee0a"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsol%2Fmauth-client-ruby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsol%2Fmauth-client-ruby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsol%2Fmauth-client-ruby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsol%2Fmauth-client-ruby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdsol","download_url":"https://codeload.github.com/mdsol/mauth-client-ruby/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226143895,"owners_count":17580245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["platform","product-quality","site-mgmt","study-conduct"],"created_at":"2024-08-06T08:02:28.549Z","updated_at":"2024-11-24T08:31:36.473Z","avatar_url":"https://github.com/mdsol.png","language":"Ruby","readme":"# MAuth-Client\n\nThis gem consists of MAuth::Client, a class to manage the information needed to both sign and authenticate requests\nand responses, and middlewares for Rack and Faraday which leverage the client's capabilities.\n\nMAuth-Client exists in a variety of languages (.Net, Go, R etc.), see the [implementations list](doc/implementations.md) for more info.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'mauth-client'\n```\n\nAnd then execute:\n```\n$ bundle\n```\n\nOr install it yourself as:\n```\n$ gem install mauth-client\n```\n\n\n## Configuration\n\nConfiguration is set through environment variables:\n\n- `MAUTH_PRIVATE_KEY`\n  - Required for signing and for authentication.\n\n- `MAUTH_PRIVATE_KEY_FILE`\n  - May be used instead of `MAUTH_PRIVATE_KEY`, mauth-client will load the file instead.\n\n- `MAUTH_APP_UUID`\n  - Required in the same circumstances where a `private_key` is required.\n\n- `MAUTH_URL`\n  - Required for authentication but not for signing. Needed to retrieve public keys. Usually this is `https://mauth.imedidata.com` for production.\n\n- `MAUTH_API_VERSION`\n  - Required for authentication but not for signing. only `v1` exists as of this writing. Defaults to `v1`.\n\n- `MAUTH_V2_ONLY_SIGN_REQUESTS`\n  - If true, all outgoing requests will be signed with only the V2 protocol. Defaults to false.\n\n- `MAUTH_V2_ONLY_AUTHENTICATE`\n  - If true, any incoming request or incoming response that does not use the V2 protocol will be rejected. Defaults to false.\n\n- `MAUTH_DISABLE_FALLBACK_TO_V1_ON_V2_FAILURE`\n  - If true, any incoming V2 requests that fail authentication will not fall back to V1 authentication. Defaults to false.\n\n- `MAUTH_V1_ONLY_SIGN_REQUESTS`\n  - If true, all outgoing requests will be signed with only the V1 protocol. Defaults to true. Note, cannot be `true` if `MAUTH_V2_ONLY_SIGN_REQUESTS` is also `true`.\n\n- `MAUTH_USE_RAILS_CACHE`\n  - If true, `Rails.cache` is used to cache public keys for authentication.\n\nThis is simply loaded and passed to either middleware or directly to a MAuth::Client instance.\nSee the documentation for [MAuth::Client#initialize](lib/mauth/client.rb) for more details of what it accepts. Usually you will want:\n\n```ruby\nMAUTH_CONF = MAuth::Client.default_config\n```\n\nThe `.default_config` method takes a number of options to tweak its expectations regarding defaults. See the\ndocumentation for [MAuth::Client.default_config](lib/mauth/client.rb) for details.\n\nThe `private_key` and `app_uuid` are required for signing and for authentication.\nThey’ll only work if the `app_uuid` has been stored in MAuth with a public key corresponding to the `private_key`.\n\nThe `mauth_baseurl` and `mauth_api_version` are required for authentication.\nThese tell the MAuth-Client where and how to communicate with the MAuth service.\n\nThe `v2_only_sign_requests` and `v2_only_authenticate` flags were added to facilitate conversion from the MAuth V1 protocol to the MAuth\nV2 protocol. By default both of these flags are false. See [Protocol Versions](#protocol-versions) below for more information about the different versions.\n\n|       | v2_only_sign_requests         | v2_only_authenticate                                                            |\n|-------|------------------------------------|--------------------------------------------------------------------------------------|\n| true  | requests are signed with only V2   | requests and responses are authenticated with only V2                                |\n| false | requests are signed with V1 and V2 | requests and responses are authenticated with the highest available protocol version |\n\n### Generating keys\n\nTo generate a private key (`mauth_key`) and its public counterpart (`mauth_key.pub`) run:\n\n```\nopenssl genrsa -out mauth_key 2048\nopenssl rsa -in mauth_key -pubout -out mauth_key.pub\n```\n\n## Rack Middleware Usage\n\nMAuth-Client provides a middleware for request authentication and response verification in mauth/rack.\n\n```ruby\nrequire 'mauth/rack'\n```\n\nIf you are using other rack middlewares, the MAuth middleware MUST come FIRST in the stack of middlewares.\nThis means it is closest to the HTTP layer, furthest from the application.\nIf any other middlewares which modify the incoming request or outgoing response lie between the HTTP layer and the MAuth middleware, incoming requests will probably fail to authenticate and outgoing response signatures will be invalid (and fail when the requester tries to authenticate them).\n\nUsing these middlewares in rails consists of calls to `config.middleware.use` in the appropriate place (see [the Rails Guides](http://guides.rubyonrails.org/rails_on_rack.html) for more info).\n\nUsing the `MAuth::Rack::ResponseSigner` middleware is optional, but highly recommended.\nIf used, this should come before the `MAuth::Rack::RequestAuthenticator` middleware.\nThe ResponseSigner can be used ONLY if you have an `app_uuid` and `private_key` specified in your mauth configuration.\n\n```ruby\nconfig.middleware.use MAuth::Rack::ResponseSigner, MAUTH_CONF\n```\n\nThen request authentication:\n\n```ruby\nconfig.middleware.use MAuth::Rack::RequestAuthenticator, MAUTH_CONF\n```\n\nHowever, assuming you have a route `/app_status`, you probably want to skip request authentication for that.\nThere is a middleware (`RequestAuthenticatorNoAppStatus`) to make that easier:\n\n```ruby\nconfig.middleware.use MAuth::Rack::RequestAuthenticatorNoAppStatus, MAUTH_CONF\n```\n\nYou may want to configure other conditions in which to bypass MAuth authentication.\nThe middleware takes an option on the `:should_authenticate_check` key, which is a ruby proc that is passed to the request's rack env and must result in a boolean.\nIf the result is true(ish), the middleware will authenticate the incoming request; if false, it will not.\nThe `:should_authenticate_check` parameter is OPTIONAL.\nIf omitted, all incoming requests will be authenticated.\n\nHere are a few example `:should_authenticate_check` procs:\n\n```ruby\nMAUTH_CONF[:should_authenticate_check] = proc do |env|\n  env['REQUEST_METHOD'] == 'GET'\nend\nconfig.middleware.use MAuth::Rack::RequestAuthenticator, MAUTH_CONF\n```\n\nAbove, env is a hash of request parameters; this hash is generated by Rack.\nThe above proc will force the middleware to authenticate only GET requests.\n\n\nAnother example:\n\n```ruby\nMAUTH_CONF[:should_authenticate_check] = proc do |env|\n  env['PATH_INFO'] == '/studies.json'\nend\nconfig.middleware.use MAuth::Rack::RequestAuthenticator, MAUTH_CONF\n```\n\nThe above proc will force the rack middleware to authenticate only requests to the \"/studies.json\" path.\nTo authenticate a group of related URIs, considered matching `env['PATH_INFO']` with one or more regular expressions.\n\nThe configuration passed to the middlewares in the above examples (`MAUTH_CONF`) is used create a new instance of `MAuth::Client`.\nIf you are managing an MAuth::Client of your own for some reason, you can pass that in on the key `:mauth_client =\u003e your_client`, and omit any other MAuth::Client configuration.\n`:should_authenticate_check` is handled by the middleware and should still be specified alongside `:mauth_client`, if you are using it.\n\nWhen the request authentication middleware determines that a request is inauthentic, it will not call the application and will respond with a 401 status code along with an error, expressed in JSON\n(Content-Type: application/json) with the following value:\n```\n{ \"errors\": { \"mauth\": [\"Unauthorized\"] } }\n```\nSuccessfully authenticated requests will be passed to the application, as will requests for which the `:should_authenticate_check` condition is false.\n\nIf the middleware is unable to authenticate the request because MAuth is unavailable and so cannot serve public keys, it responds with a 500 status code and an error expressed in JSON with the value:\n```\n{ \"errors\": { \"mauth\": [\"Could not determine request authenticity\"] } }\n```\n\n## Examples\n\nPutting all this together, here are typical examples (in rails you would put that code in an initializer):\n\n```ruby\nrequire 'mauth/rack'\n\nMAUTH_CONF = MAuth::Client.default_config\n\n# ResponseSigner OPTIONAL; only use if you are registered in mauth service\nRails.application.config.middleware.insert_after Rack::Runtime, MAuth::Rack::ResponseSigner, MAUTH_CONF\nif Rails.env.test? || Rails.env.development?\n  require 'mauth/fake/rack'\n  Rails.application.config.middleware.insert_after MAuth::Rack::ResponseSigner, MAuth::Rack::RequestAuthenticationFaker, MAUTH_CONF\nelse\n  Rails.application.config.middleware.insert_after MAuth::Rack::ResponseSigner, MAuth::Rack::RequestAuthenticatorNoAppStatus, MAUTH_CONF\nend\n```\n\nWith `:should_authenticate_check`:\n\n```ruby\nrequire 'mauth/rack'\n\nMAUTH_CONF = MAuth::Client.default_config\n# authenticate all requests which pass the some_condition_of check and aren't /app_status with MAuth\nMAUTH_CONF[:should_authenticate_check] = proc do |env|\n  some_condition_of(env)\nend\n\n# ResponseSigner OPTIONAL; only use if you are registered in mauth service\nRails.application.config.middleware.insert_after Rack::Runtime, MAuth::Rack::ResponseSigner, MAUTH_CONF\nif Rails.env.test? || Rails.env.development?\n  require 'mauth/fake/rack'\n  Rails.application.config.middleware.insert_after MAuth::Rack::ResponseSigner, MAuth::Rack::RequestAuthenticationFaker, MAUTH_CONF\nelse\n  Rails.application.config.middleware.insert_after MAuth::Rack::ResponseSigner, MAuth::Rack::RequestAuthenticatorNoAppStatus, MAUTH_CONF\nend\n```\n\n## Fake middleware\n\nFor testing purposes, you may wish to use middleware which does not perform actual authentication.\nMAuth provides this, as `MAuth::Rack::RequestAuthenticationFaker`.\nRequests are still checked for the presence of an MAuth signature - this is necessary as many applications rely on the `app_uuid` identified in the signature, so it cannot be ignored entirely.\nHowever, the validity of the public key is not checked in the MAuth service, and the authenticity of the request is not verified by its signature.\n\nThis example code may augment the above examples to disable authentication in test mode:\n\n```ruby\nrequire 'mauth/fake/rack'\nauthenticator = Rails.env != 'test' ? MAuth::Rack::RequestAuthenticator : MAuth::Rack::RequestAuthenticationFaker\nconfig.middleware.use authenticator, MAUTH_CONF\n```\n\n## Faraday Middleware Usage\n\nIf you are making outgoing HTTP requests using Faraday, adding MAuth Faraday middleware is much the same as adding rack middleware.\nBuilding your connection will look like:\n\n```ruby\nFaraday.new(some_args) do |builder|\n  builder.use MAuth::Faraday::RequestSigner, MAUTH_CONF\n  builder.use MAuth::Faraday::ResponseAuthenticator, MAUTH_CONF\n  builder.adapter Faraday.default_adapter\nend\n```\n\nThe Faraday middleware MUST come LAST in the stack of middleware.\nAs with the rack middleware, this means it will be right next to the HTTP adapter.\n\nOnly use the `MAuth::Faraday::ResponseAuthenticator` middleware if you are expecting the service you are communicating with to sign its responses (all services which are aware of MAuth _should_ be doing this).\n\n`MAUTH_CONF` is the same as in Rack middleware, and as with the Rack middleware is used to initialize a `MAuth::Client` instance.\nAlso as with the Rack middleware, you can pass in a `MAuth::Client` instance you are using yourself on the `:mauth_client` key, and omit any other configuration.\n\nBoth `MAuth::Faraday::ResponseAuthenticator` and `MAuth::Faraday::RequestSigner` cannot be used without a `private_key` and `app_uuid`.\n\nIf a response which does not appear to be authentic is received by the `MAuth::Faraday::ResponseAuthenticator` middleware, a `MAuth::InauthenticError` will be raised.\n\nIf the MAuth service cannot be reached, and therefore the authenticity of a response cannot be verified by ResponseAuthenticator, then a `MAuth::UnableToAuthenticateError` will be raised.\n\n## Other Request and Response signing\n\nIf you are not using Faraday, you will need to sign your own requests.\n\nInstantiate a `MAuth::Client` with the same configuration as the middlewares, as documented on [MAuth::Client#initialize](lib/mauth/client.rb).\nWe'll call this `mauth_client`.\n\n`mauth_client` has a method `#signed_headers` which takes either a `MAuth::Request` or `MAuth::Response` object, and generates HTTP headers which can be added to the request or response to indicate authenticity.\nCreate a `MAuth::Request` object from the information in your HTTP request, whatever its form:\n\n```ruby\nrequire 'mauth/request_and_response'\nrequest = MAuth::Request.new(verb: my_verb, request_url: my_request_url, body: my_body, query_string: my_query_string)\n```\n`mauth_client.signed_headers(request)` will then return mauth headers which you can apply to your request.\n\n## Warning\n\nDuring development classes are typically not cached in Rails applications.\nIf this is the case, be aware that the MAuth-Client middleware object will be instantiated anew for each request;\nthis will cause applications performing local authentication to fetch public keys before each request is authenticated.\n\n## Protocol Versions\n\nThe mauth V2 protocol was added as of v5.0.0. This protocol updates the string_to_sign to include query parameters, uses different authentication header names, and has a few other changes. See this document for more information: (DOC?). By default MAuth-Client will authenticate incoming requests with only the highest version of the protocol present, and sign their outgoing responses with only the version used to authenticate the request. By default MAuth-Client will sign outgoing requests with both the V1 and V2 protocols, and authenticate their incoming responses with only the highest version of the protocol present.\nIf the `v2_only_sign_requests` flag is true all outgoing requests will be signed with only the V2 protocol (outgoing responses will still be signed with whatever protocol used to authenticate the request). If the `v2_only_authenticate` flag is true then MAuth-Client will reject any incoming request or incoming response that does not use the V2 protocol.\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdsol%2Fmauth-client-ruby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdsol%2Fmauth-client-ruby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdsol%2Fmauth-client-ruby/lists"}