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_tokenmaint
commit
2ca91d1ee0
|
@ -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
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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)
|
|||
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)
|
|||
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)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -141,6 +141,7 @@ struct credential {
|
|||
char *protocol;
|
||||
char *host;
|
||||
char *path;
|
||||
char *oauth_refresh_token;
|
||||
timestamp_t password_expiry_utc;
|
||||
};
|
||||
|
||||
|
|
|
@ -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() {
|
|||
'
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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…
Reference in New Issue