Skip to content

Commit 0610346

Browse files
authored
Merge pull request #665 from ruby-oauth/mtls
2 parents 310ccce + 5c08737 commit 0610346

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## [Unreleased]
88
### Added
99
- improved documentation by @pboling
10+
- Document Mutual TLS (mTLS) usage with example in README (connection_opts.ssl client_cert/client_key and auth_scheme: :tls_client_auth)
1011
- documentation notes in code comments and README highlighting OAuth 2.1 differences, with references, such as:
1112
- PKCE required for auth code,
1213
- exact redirect URI match,

README.md

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,55 @@ access.revoke(token_type_hint: :refresh_token)
913913

914914
### Client Configuration Tips
915915

916-
- Authentication schemes for the token request:
916+
#### Mutual TLS (mTLS) client authentication
917+
918+
Some providers require OAuth requests (including the token request and subsequent API calls) to be sender‑constrained using mutual TLS (mTLS). With this gem, you enable mTLS by providing a client certificate/private key to Faraday via connection_opts.ssl and, if your provider requires it for client authentication, selecting the tls_client_auth auth_scheme.
919+
920+
Example using PEM files (certificate and key):
921+
922+
```ruby
923+
require "oauth2"
924+
require "openssl"
925+
926+
client = OAuth2::Client.new(
927+
ENV.fetch("CLIENT_ID"),
928+
ENV.fetch("CLIENT_SECRET"),
929+
site: "https://example.com",
930+
authorize_url: "/oauth/authorize/",
931+
token_url: "/oauth/token/",
932+
auth_scheme: :tls_client_auth, # if your AS requires mTLS-based client authentication
933+
connection_opts: {
934+
ssl: {
935+
client_cert: OpenSSL::X509::Certificate.new(File.read("localhost.pem")),
936+
client_key: OpenSSL::PKey::RSA.new(File.read("localhost-key.pem")),
937+
# Optional extras, uncomment as needed:
938+
# ca_file: "/path/to/ca-bundle.pem", # custom CA(s)
939+
# verify: true # enable server cert verification (recommended)
940+
},
941+
},
942+
)
943+
944+
# Example token request (any grant type can be used). The mTLS handshake
945+
# will occur automatically on HTTPS calls using the configured cert/key.
946+
access = client.client_credentials.get_token
947+
948+
# Subsequent resource requests will also use mTLS on HTTPS endpoints of `site`:
949+
resp = access.get("/v1/protected")
950+
```
951+
952+
Notes:
953+
- Files must contain the appropriate PEMs. The private key may be encrypted; if so, pass a password to OpenSSL::PKey::RSA.new(File.read(path), ENV["KEY_PASSWORD"]).
954+
- If your certificate and key are in a PKCS#12/PFX bundle, you can load them like:
955+
- p12 = OpenSSL::PKCS12.new(File.read("client.p12"), ENV["P12_PASSWORD"])
956+
- client_cert = p12.certificate; client_key = p12.key
957+
- Server trust:
958+
- If your environment does not have system CAs, specify ca_file or ca_path inside the ssl: hash.
959+
- Keep verify: true in production. Set verify: false only for local testing.
960+
- Faraday adapter: Any adapter that supports Ruby’s OpenSSL should work. net_http (default) and net_http_persistent are common choices.
961+
- Scope of mTLS: The SSL client cert is applied to any HTTPS request made by this client (token and resource requests) to the configured site base URL (and absolute URLs you call with the same client).
962+
- OIDC tie-in: Some OPs require tls_client_auth at the token endpoint per OIDC/OAuth specifications. That is enabled via auth_scheme: :tls_client_auth as shown above.
963+
964+
#### Authentication schemes for the token request
917965

918966
```ruby
919967
OAuth2::Client.new(
@@ -924,7 +972,7 @@ OAuth2::Client.new(
924972
)
925973
```
926974

927-
- Faraday connection, timeouts, proxy, custom adapter/middleware:
975+
#### Faraday connection, timeouts, proxy, custom adapter/middleware:
928976

929977
```ruby
930978
client = OAuth2::Client.new(
@@ -943,7 +991,10 @@ client = OAuth2::Client.new(
943991
end
944992
```
945993

946-
- Redirection: The library follows up to `max_redirects` (default 5). You can override per-client via `options[:max_redirects]`.
994+
#### Redirection
995+
996+
The library follows up to `max_redirects` (default 5).
997+
You can override per-client via `options[:max_redirects]`.
947998

948999
### Handling Responses and Errors
9491000

0 commit comments

Comments
 (0)