Skip to content

Commit b49f42e

Browse files
committed
[registry] Accept empty scope during token auth challenge
The distribution spec (https://distribution.github.io/distribution/spec/auth/scope/#authorization-server-use) mentions that the access token provided during auth challenge "may include a scope" which means that it's not necessary to have one either to comply with the spec. Additionally, this is something that is already accepted by containerd which will simply log a warning when no scope is specified: https://github.com/containerd/containerd/blob/main/core/remotes/docker/auth/fetch.go#L64 To match with what containerd and the spec suggest, the commit modifies the `parse_auth` logic to accept and empty `scope` field. It also logs the same warning as containerd.
1 parent e1dffec commit b49f42e

1 file changed

Lines changed: 23 additions & 6 deletions

File tree

storage/src/backend/registry.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -437,17 +437,21 @@ impl RegistryState {
437437
Some(Auth::Basic(BasicAuth { realm }))
438438
}
439439
"Bearer" => {
440-
if !paras.contains_key("realm")
441-
|| !paras.contains_key("service")
442-
|| !paras.contains_key("scope")
443-
{
440+
if !paras.contains_key("realm") || !paras.contains_key("service") {
444441
return None;
445442
}
446443

444+
let scope = if let Some(scope) = paras.get("scope") {
445+
(*scope).to_string()
446+
} else {
447+
warn!("no scope specified for token auth challenge");
448+
String::new()
449+
};
450+
447451
Some(Auth::Bearer(BearerAuth {
448452
realm: (*paras.get("realm").unwrap()).to_string(),
449453
service: (*paras.get("service").unwrap()).to_string(),
450-
scope: (*paras.get("scope").unwrap()).to_string(),
454+
scope: scope,
451455
}))
452456
}
453457
_ => None,
@@ -1115,12 +1119,25 @@ mod tests {
11151119
_ => panic!("failed to parse `Bearer` authentication header"),
11161120
}
11171121

1122+
// No scope is accetpable
1123+
let str = "Bearer realm=\"https://auth.my-registry.com/token\",service=\"my-registry.com\"";
1124+
let header = HeaderValue::from_str(str).unwrap();
1125+
let auth = RegistryState::parse_auth(&header).unwrap();
1126+
match auth {
1127+
Auth::Bearer(auth) => {
1128+
assert_eq!(&auth.realm, "https://auth.my-registry.com/token");
1129+
assert_eq!(&auth.service, "my-registry.com");
1130+
assert_eq!(&auth.scope, "");
1131+
}
1132+
_ => panic!("failed to parse `Bearer` authentication header without scope"),
1133+
}
1134+
11181135
let str = "Basic realm=\"https://auth.my-registry.com/token\"";
11191136
let header = HeaderValue::from_str(str).unwrap();
11201137
let auth = RegistryState::parse_auth(&header).unwrap();
11211138
match auth {
11221139
Auth::Basic(auth) => assert_eq!(&auth.realm, "https://auth.my-registry.com/token"),
1123-
_ => panic!("failed to parse `Bearer` authentication header"),
1140+
_ => panic!("failed to parse `Basic` authentication header"),
11241141
}
11251142

11261143
let str = "Base realm=\"https://auth.my-registry.com/token\"";

0 commit comments

Comments
 (0)