credential: add a field called "ephemeral"

Now that we have support for a wide variety of types of authentication, it's important to indicate to other credential helpers whether they should store credentials, since not every credential helper may intuitively understand all possible values of the authtype field. Do so with a boolean field called "ephemeral", to indicate whether the credential is expected to be temporary. For example, in HTTP Digest authentication, the Authorization header value is based off a nonce. It isn't useful to store this value for later use because reusing the credential long term will not result in successful authentication due to the nonce necessarily differing. An additional case is potentially short-lived credentials, which may last only a few hours. It similarly wouldn't be helper for other credential helpers to attempt to provide these much later. We do still pass the value to "git credential store" or "git credential erase", since it may be helpful to the original helper to know whether the operation was successful. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed Apr 17, 2024 at 00:02 UTC 2ae6dc686d79a6dcf52e67dbe886f1bfca8876d5
3 files changed +35
credential.c
+4
@@ -289,6 +289,8 @@ int credential_read(struct credential *c, FILE *fp,
289 } else if (!strcmp(key, "path")) {
290 free(c->path);
291 c->path = xstrdup(value);
292 + } else if (!strcmp(key, "ephemeral")) {
293 + c->ephemeral = !!git_config_bool("ephemeral", value);
294 } else if (!strcmp(key, "wwwauth[]")) {
295 strvec_push(&c->wwwauth_headers, value);
296 } else if (!strcmp(key, "capability[]") && !strcmp(value, "authtype")) {
@@ -339,6 +341,8 @@ void credential_write(const struct credential *c, FILE *fp,
341 credential_write_item(fp, "capability[]", "authtype", 0);
342 credential_write_item(fp, "authtype", c->authtype, 0);
343 credential_write_item(fp, "credential", c->credential, 0);
344 + if (c->ephemeral)
345 + credential_write_item(fp, "ephemeral", "1", 0);
346 }
347 credential_write_item(fp, "protocol", c->protocol, 1);
348 credential_write_item(fp, "host", c->host, 1);
credential.h
+1
@@ -152,6 +152,7 @@ struct credential {
152 unsigned header_is_last_match:1;
153
154 unsigned approved:1,
155 + ephemeral:1,
156 configured:1,
157 quit:1,
158 use_http_path:1,
t/t0300-credentials.sh
+30
@@ -51,6 +51,17 @@ test_expect_success 'setup helper scripts' '
51 test -z "$credential" || echo credential=$credential
52 EOF
53
54 + write_script git-credential-verbatim-ephemeral <<-\EOF &&
55 + authtype=$1; shift
56 + credential=$1; shift
57 + . ./dump
58 + echo capability[]=authtype
59 + test -z "${capability##*authtype*}" || exit 0
60 + test -z "$authtype" || echo authtype=$authtype
61 + test -z "$credential" || echo credential=$credential
62 + echo "ephemeral=1"
63 + EOF
64 +
65 write_script git-credential-verbatim-with-expiry <<-\EOF &&
66 user=$1; shift
67 pass=$1; shift
@@ -99,6 +110,25 @@ test_expect_success 'credential_fill invokes helper with credential' '
110 EOF
111 '
112
113 +test_expect_success 'credential_fill invokes helper with ephemeral credential' '
114 + check fill "verbatim-ephemeral Bearer token" <<-\EOF
115 + capability[]=authtype
116 + protocol=http
117 + host=example.com
118 + --
119 + capability[]=authtype
120 + authtype=Bearer
121 + credential=token
122 + ephemeral=1
123 + protocol=http
124 + host=example.com
125 + --
126 + verbatim-ephemeral: get
127 + verbatim-ephemeral: capability[]=authtype
128 + verbatim-ephemeral: protocol=http
129 + verbatim-ephemeral: host=example.com
130 + EOF
131 +'
132
133 test_expect_success 'credential_fill invokes multiple helpers' '
134 check fill useless "verbatim foo bar" <<-\EOF