Extract an [`Identity`] from the peer certificates presented during a TLS handshake. Returns `None` if no client certificate was presented.
(tls_stream: &tokio_rustls::server::TlsStream<S>)
| 742 | /// Extract an [`Identity`] from the peer certificates presented during a TLS |
| 743 | /// handshake. Returns `None` if no client certificate was presented. |
| 744 | pub fn extract_peer_identity<S>(tls_stream: &tokio_rustls::server::TlsStream<S>) -> Option<Identity> |
| 745 | where |
| 746 | S: AsyncRead + AsyncWrite + Unpin, |
| 747 | { |
| 748 | use crate::auth::identity::IdentityProvider; |
| 749 | use x509_parser::prelude::*; |
| 750 | |
| 751 | let (_, server_conn) = tls_stream.get_ref(); |
| 752 | let certs = server_conn.peer_certificates()?; |
| 753 | let first = certs.first()?; |
| 754 | |
| 755 | let (_, cert) = X509Certificate::from_der(first.as_ref()).ok()?; |
| 756 | let subject = cert.subject(); |
| 757 | |
| 758 | let cn = subject |
| 759 | .iter_common_name() |
| 760 | .next() |
| 761 | .and_then(|attr| attr.as_str().ok()) |
| 762 | .unwrap_or("unknown") |
| 763 | .to_string(); |
| 764 | |
| 765 | let roles: Vec<String> = subject |
| 766 | .iter_organizational_unit() |
| 767 | .filter_map(|attr| attr.as_str().ok().map(String::from)) |
| 768 | .collect(); |
| 769 | |
| 770 | Some(Identity { |
| 771 | subject: cn.clone(), |
| 772 | display_name: Some(cn), |
| 773 | roles, |
| 774 | scopes: Vec::new(), |
| 775 | provider: IdentityProvider::Mtls, |
| 776 | }) |
| 777 | } |
| 778 | |
| 779 | /// Boxed body type for uniform handling. |
| 780 | pub struct BoxBody( |
no test coverage detected