Browse Source

Merge branch 'mh/credential-oauth-refresh-token'

The credential subsystem learns to help OAuth framework.

* mh/credential-oauth-refresh-token:
  credential: new attribute oauth_refresh_token
main
Junio C Hamano 2 years ago
parent
commit
2ca91d1ee0
  1. 6
      Documentation/git-credential.txt
  2. 3
      builtin/credential-cache--daemon.c
  3. 6
      credential.c
  4. 1
      credential.h
  5. 30
      t/lib-credential.sh
  6. 18
      t/t0300-credentials.sh
  7. 1
      t/t0301-credential-cache.sh

6
Documentation/git-credential.txt

@ -156,6 +156,12 @@ Git understands the following attributes: @@ -156,6 +156,12 @@ Git understands the following attributes:
When reading credentials from helpers, `git credential fill` ignores expired
passwords. Represented as Unix time UTC, seconds since 1970.

`oauth_refresh_token`::

An OAuth refresh token may accompany a password that is an OAuth access
token. Helpers must treat this attribute as confidential like the password
attribute. Git itself has no special behaviour for this attribute.

`url`::

When this special attribute is read by `git credential`, the

3
builtin/credential-cache--daemon.c

@ -134,6 +134,9 @@ static void serve_one_client(FILE *in, FILE *out) @@ -134,6 +134,9 @@ static void serve_one_client(FILE *in, FILE *out)
if (e->item.password_expiry_utc != TIME_MAX)
fprintf(out, "password_expiry_utc=%"PRItime"\n",
e->item.password_expiry_utc);
if (e->item.oauth_refresh_token)
fprintf(out, "oauth_refresh_token=%s\n",
e->item.oauth_refresh_token);
}
}
else if (!strcmp(action.buf, "exit")) {

6
credential.c

@ -25,6 +25,7 @@ void credential_clear(struct credential *c) @@ -25,6 +25,7 @@ void credential_clear(struct credential *c)
free(c->path);
free(c->username);
free(c->password);
free(c->oauth_refresh_token);
string_list_clear(&c->helpers, 0);
strvec_clear(&c->wwwauth_headers);

@ -246,6 +247,9 @@ int credential_read(struct credential *c, FILE *fp) @@ -246,6 +247,9 @@ int credential_read(struct credential *c, FILE *fp)
c->password_expiry_utc = parse_timestamp(value, NULL, 10);
if (c->password_expiry_utc == 0 || errno == ERANGE)
c->password_expiry_utc = TIME_MAX;
} else if (!strcmp(key, "oauth_refresh_token")) {
free(c->oauth_refresh_token);
c->oauth_refresh_token = xstrdup(value);
} else if (!strcmp(key, "url")) {
credential_from_url(c, value);
} else if (!strcmp(key, "quit")) {
@ -281,6 +285,7 @@ void credential_write(const struct credential *c, FILE *fp) @@ -281,6 +285,7 @@ void credential_write(const struct credential *c, FILE *fp)
credential_write_item(fp, "path", c->path, 0);
credential_write_item(fp, "username", c->username, 0);
credential_write_item(fp, "password", c->password, 0);
credential_write_item(fp, "oauth_refresh_token", c->oauth_refresh_token, 0);
if (c->password_expiry_utc != TIME_MAX) {
char *s = xstrfmt("%"PRItime, c->password_expiry_utc);
credential_write_item(fp, "password_expiry_utc", s, 0);
@ -406,6 +411,7 @@ void credential_reject(struct credential *c) @@ -406,6 +411,7 @@ void credential_reject(struct credential *c)

FREE_AND_NULL(c->username);
FREE_AND_NULL(c->password);
FREE_AND_NULL(c->oauth_refresh_token);
c->password_expiry_utc = TIME_MAX;
c->approved = 0;
}

1
credential.h

@ -141,6 +141,7 @@ struct credential { @@ -141,6 +141,7 @@ struct credential {
char *protocol;
char *host;
char *path;
char *oauth_refresh_token;
timestamp_t password_expiry_utc;
};


30
t/lib-credential.sh

@ -43,6 +43,7 @@ helper_test_clean() { @@ -43,6 +43,7 @@ helper_test_clean() {
reject $1 https example.com store-user
reject $1 https example.com user1
reject $1 https example.com user2
reject $1 https example.com user4
reject $1 http path.tld user
reject $1 https timeout.tld user
reject $1 https sso.tld
@ -327,6 +328,35 @@ helper_test_timeout() { @@ -327,6 +328,35 @@ helper_test_timeout() {
'
}

helper_test_oauth_refresh_token() {
HELPER=$1

test_expect_success "helper ($HELPER) stores oauth_refresh_token" '
check approve $HELPER <<-\EOF
protocol=https
host=example.com
username=user4
password=pass
oauth_refresh_token=xyzzy
EOF
'

test_expect_success "helper ($HELPER) gets oauth_refresh_token" '
check fill $HELPER <<-\EOF
protocol=https
host=example.com
username=user4
--
protocol=https
host=example.com
username=user4
password=pass
oauth_refresh_token=xyzzy
--
EOF
'
}

write_script askpass <<\EOF
echo >&2 askpass: $*
what=$(echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z)

18
t/t0300-credentials.sh

@ -214,6 +214,24 @@ test_expect_success 'credential_approve stores password expiry' ' @@ -214,6 +214,24 @@ test_expect_success 'credential_approve stores password expiry' '
EOF
'

test_expect_success 'credential_approve stores oauth refresh token' '
check approve useless <<-\EOF
protocol=http
host=example.com
username=foo
password=bar
oauth_refresh_token=xyzzy
--
--
useless: store
useless: protocol=http
useless: host=example.com
useless: username=foo
useless: password=bar
useless: oauth_refresh_token=xyzzy
EOF
'

test_expect_success 'do not bother storing password-less credential' '
check approve useless <<-\EOF
protocol=http

1
t/t0301-credential-cache.sh

@ -29,6 +29,7 @@ test_atexit 'git credential-cache exit' @@ -29,6 +29,7 @@ test_atexit 'git credential-cache exit'

# test that the daemon works with no special setup
helper_test cache
helper_test_oauth_refresh_token cache

test_expect_success 'socket defaults to ~/.cache/git/credential/socket' '
test_when_finished "

Loading…
Cancel
Save