git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Aditya Garg <gargaditya08@live.com>
To: Julian Swagemakers <julian@swagemakers.org>,
	git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>
Cc: M Hickford <mirth.hickford@gmail.com>,
	sandals@crustytoothpaste.net, Shengyu Qu <wiagn233@outlook.com>
Subject: [PATCH v4 1/3] send-email: implement SMTP bearer authentication
Date: Wed, 23 Apr 2025 12:19:45 +0000	[thread overview]
Message-ID: <PN3PR01MB9597776CB37BE7B05A7ADD80B8BA2@PN3PR01MB9597.INDPRD01.PROD.OUTLOOK.COM> (raw)
In-Reply-To: <PN3PR01MB9597A83D537E3AE96144227EB8BA2@PN3PR01MB9597.INDPRD01.PROD.OUTLOOK.COM>

From: Julian Swagemakers <julian@swagemakers.org>

Manually send SMTP AUTH command for auth type OAUTHBEARER and XOAUTH2.
This is necessary since they are currently not supported by the Perls
Authen::SASL module.

The bearer token needs to be passed in as the password. This can be done
with git-credential-oauth[0] after minor modifications[1]. Which will
allow using git send-email with Gmail and oauth2 authentication:

    [credential]
        helper = cache --timeout 7200    # two hours
        helper = oauth
    [sendemail]
        smtpEncryption = tls
        smtpServer = smtp.gmail.com
        smtpUser = example@gmail.com
        smtpServerPort = 587
        smtpauth = OAUTHBEARER

As well as Office 365 accounts:

    [credential]
        helper = cache --timeout 7200   # two hours
        helper = oauth
    [sendemail]
        smtpEncryption = tls
        smtpServer = smtp.office365.com
        smtpUser = example@example.com
        smtpServerPort = 587
        smtpauth = XOAUTH2

[0] https://github.com/hickford/git-credential-oauth
[1] https://github.com/hickford/git-credential-oauth/issues/48

Tested-by: M Hickford <mirth.hickford@gmail.com>
Signed-off-by: Julian Swagemakers <julian@swagemakers.org>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
 Documentation/git-send-email.adoc |  5 ++-
 git-send-email.perl               | 64 ++++++++++++++++++++++++++++++-
 2 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-send-email.adoc b/Documentation/git-send-email.adoc
index 7f223db42d..1bf75c060d 100644
--- a/Documentation/git-send-email.adoc
+++ b/Documentation/git-send-email.adoc
@@ -213,7 +213,10 @@ SMTP server and if it is supported by the utilized SASL library, the mechanism
 is used for authentication. If neither 'sendemail.smtpAuth' nor `--smtp-auth`
 is specified, all mechanisms supported by the SASL library can be used. The
 special value 'none' maybe specified to completely disable authentication
-independently of `--smtp-user`
+independently of `--smtp-user`. Specifying `OAUTHBEARER` or `XOAUTH2` will
+bypass SASL negotiation and force bearer authentication. In this case the
+bearer token must be provided with `--smtp-pass` or using a credential helper
+and `--smtp-encryption=tls` must be set.
 
 --smtp-pass[=<password>]::
 	Password for SMTP-AUTH. The argument is optional: If no
diff --git a/git-send-email.perl b/git-send-email.perl
index 1f613fa979..a6cafda29c 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1398,6 +1398,63 @@ sub smtp_host_string {
 	}
 }
 
+sub generate_oauthbearer_string {
+	# This will generate the oauthbearer string used for authentication.
+	#
+	# "n,a=" {User} ",^Ahost=" {Host} "^Aport=" {Port} "^Aauth=Bearer " {Access Token} "^A^A
+	#
+	# The first part `n,a=" {User} ",` is the gs2 header described in RFC5801.
+	# * gs2-cb-flag `n` -> client does not support CB
+	# * gs2-authzid `a=" {User} "`
+	#
+	# The second part are key value pairs containing host, port and auth as
+	# described in RFC7628.
+	#
+	# https://datatracker.ietf.org/doc/html/rfc5801
+	# https://datatracker.ietf.org/doc/html/rfc7628
+	my $username = shift;
+	my $token = shift;
+	return "n,a=$username,\001port=$smtp_server_port\001auth=Bearer $token\001\001";
+}
+
+sub generate_xoauth2_string {
+	# "user=" {User} "^Aauth=Bearer " {Access Token} "^A^A"
+	# https://developers.google.com/gmail/imap/xoauth2-protocol#initial_client_response
+	my $username = shift;
+	my $token = shift;
+	return "user=$username\001auth=Bearer $token\001\001";
+}
+
+sub smtp_bearer_auth {
+	my $username = shift;
+	my $token = shift;
+	my $auth_string;
+	if ($smtp_encryption ne "tls") {
+		# As described in RFC7628 TLS is required and will be enforced
+		# at this point.
+		#
+		# https://datatracker.ietf.org/doc/html/rfc7628#section-3
+		die sprintf(__("For %s TLS is required."), $smtp_auth);
+	}
+	if ($smtp_auth eq "OAUTHBEARER") {
+		$auth_string = generate_oauthbearer_string($username, $token);
+	} elsif ($smtp_auth eq "XOAUTH2") {
+		$auth_string = generate_xoauth2_string($username, $token);
+	}
+	my $encoded_auth_string = MIME::Base64::encode($auth_string, "");
+	$smtp->command("AUTH $smtp_auth $encoded_auth_string\r\n");
+	use Net::Cmd qw(CMD_OK);
+	if ($smtp->response() == CMD_OK){
+		return 1;
+	} else {
+		# Send dummy request on authentication failure according to rfc7628.
+		# https://datatracker.ietf.org/doc/html/rfc7628#section-3.2.3
+		$smtp->command(MIME::Base64::encode("\001"));
+		$smtp->response();
+		return 0;
+	}
+}
+
 # Returns 1 if authentication succeeded or was not necessary
 # (smtp_user was not specified), and 0 otherwise.
 
@@ -1436,7 +1493,12 @@ sub smtp_auth_maybe {
 
 		# catch all SMTP auth error in a unified eval block
 		eval {
-			if ($smtp_auth) {
+			if (defined $smtp_auth && ($smtp_auth eq "OAUTHBEARER" || $smtp_auth eq "XOAUTH2")) {
+				# Since Authen:SASL does not support XOAUTH2 nor OAUTHBEARER we will
+				# manually authenticate for these types. The password field should
+				# contain the auth token at this point.
+				$result = smtp_bearer_auth($cred->{'username'}, $cred->{'password'});
+			} elsif ($smtp_auth) {
 				my $sasl = Authen::SASL->new(
 					mechanism => $smtp_auth,
 					callback => {
-- 
2.49.0


  reply	other threads:[~2025-04-23 12:29 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-23 12:19 [PATCH v4 0/3] send-email: add oauth2 support and fix outlook breaking threads Aditya Garg
2025-04-23 12:19 ` Aditya Garg [this message]
2025-04-23 18:04   ` [PATCH v4 1/3] send-email: implement SMTP bearer authentication Junio C Hamano
2025-04-23 18:33     ` Aditya Garg
2025-04-24  6:36       ` Greg Kroah-Hartman
2025-04-24  8:23         ` Aditya Garg
2025-04-23 12:19 ` [PATCH v4 2/3] send-email: retrieve Message-ID from outlook SMTP server Aditya Garg
2025-04-23 18:54   ` Junio C Hamano
2025-04-23 22:52   ` brian m. carlson
2025-04-24  3:42     ` Aditya Garg
2025-04-23 12:19 ` [PATCH v4 3/3] send-email: add option to generate passswords like OAuth2 tokens Aditya Garg
2025-04-23 19:03   ` Junio C Hamano
2025-04-24  3:29     ` Aditya Garg
2025-04-24 12:43       ` Junio C Hamano
2025-04-23 20:50 ` [PATCH v4 0/3] send-email: add oauth2 support and fix outlook breaking threads M Hickford
2025-04-24  3:44   ` Aditya Garg
2025-04-24  7:53 ` [PATCH v5 " Aditya Garg
2025-04-24  7:53   ` [PATCH v5 1/3] send-email: implement SMTP bearer authentication Aditya Garg
2025-04-24 12:12     ` Julian Swagemakers
     [not found]     ` <CACOoB6jE=DgpYYaudhqTVDRd2SCz++aog7QYwTQs6-MAD8dBuw@mail.gmail.com>
2025-04-24 18:22       ` Aditya Garg
2025-04-24 19:20         ` Erik Huelsmann
2025-04-25  6:19         ` Julian Swagemakers
2025-04-25  6:25           ` Aditya Garg
2025-04-25  9:45           ` Aditya Garg
2025-04-25 10:17             ` Erik Hulsmann
2025-04-24 18:23       ` Aditya Garg
2025-04-24  7:53   ` [PATCH v5 2/3] send-email: retrieve Message-ID from outlook SMTP server Aditya Garg
2025-04-24 13:09     ` Greg Kroah-Hartman
2025-04-26 18:11       ` Yao Zi
2025-04-27 20:05         ` Aditya Garg
2025-04-28  4:16           ` Yao Zi
2025-04-27 19:44       ` Aditya Garg
2025-04-24  7:53   ` [PATCH v5 3/3] send-email: add option to generate passswords like OAuth2 tokens Aditya Garg
2025-04-24 12:28     ` Julian Swagemakers
2025-04-24 12:53       ` Aditya Garg
2025-04-24 15:20         ` Junio C Hamano
2025-04-24 15:46           ` Aditya Garg
2025-04-24 16:58             ` Junio C Hamano
2025-04-25 10:09 ` [PATCH v6 0/1] send-email: add oauth2 support and fix outlook breaking threads Aditya Garg
2025-04-25 10:09   ` [PATCH v6 1/1] send-email: retrieve Message-ID from outlook SMTP server Aditya Garg
2025-04-25 15:04     ` Aditya Garg
2025-04-25 16:22       ` Erik Huelsmann
2025-04-25 17:08         ` Junio C Hamano
2025-04-25 19:05           ` Erik Huelsmann
2025-04-25 19:08             ` Aditya Garg
2025-04-25 17:23     ` Junio C Hamano
2025-04-25 19:05       ` Aditya Garg
2025-04-26  8:36       ` Aditya Garg
2025-04-26  9:03         ` Eric Sunshine
2025-04-26 17:40           ` Aditya Garg
2025-04-28 16:52         ` Junio C Hamano
2025-04-28 17:52           ` [PATCH] send-email: add --smtp-outlook-id-tweak option Aditya Garg
2025-04-28 17:57             ` [PATCH v2] " Aditya Garg
2025-04-28 20:47               ` Junio C Hamano
2025-04-29  3:44                 ` Aditya Garg
2025-04-29 10:52             ` [PATCH v3] send-email: add --[no-]outlook-id-fix option Aditya Garg
2025-04-29 11:00               ` Aditya Garg
2025-04-29 15:57               ` Junio C Hamano
2025-04-29 16:24               ` Junio C Hamano
2025-04-29 16:26                 ` Aditya Garg
2025-04-29 16:37             ` [PATCH v4] " Aditya Garg
2025-04-29 23:08               ` Junio C Hamano
2025-04-30  8:31                 ` Aditya Garg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=PN3PR01MB9597776CB37BE7B05A7ADD80B8BA2@PN3PR01MB9597.INDPRD01.PROD.OUTLOOK.COM \
    --to=gargaditya08@live.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=julian@swagemakers.org \
    --cc=mirth.hickford@gmail.com \
    --cc=sandals@crustytoothpaste.net \
    --cc=wiagn233@outlook.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).