mirror of
https://github.com/juanfont/headscale.git
synced 2026-11-04 12:39:25 +09:00
api/v2: name the token's tags in the token answer
Only a token that can assign tags names them, as Tailscale's answer does.
This commit is contained in:
1 parent
2703082a20
commit
8baba788a0
3 files changed
+25
-16
No files matched your search
@@ -35,6 +35,9 @@ type tokenResponse struct {
|
||||
TokenType string `json:"token_type"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
Scope string `json:"scope,omitempty"`
|
||||
// Tags names the tags of a token that can assign them, as Tailscale's
|
||||
// answer does; a reader token's answer has none.
|
||||
Tags string `json:"tags,omitempty"`
|
||||
}
|
||||
|
||||
// oauthTokenHandler implements the client-credentials grant (RFC 6749 §4.4):
|
||||
@@ -110,12 +113,20 @@ func oauthTokenHandler(b Backend) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, tokenResponse{
|
||||
resp := tokenResponse{
|
||||
AccessToken: tokenStr,
|
||||
TokenType: "Bearer",
|
||||
ExpiresIn: int(accessTokenTTL.Seconds()),
|
||||
Scope: strings.Join(token.Scopes, " "),
|
||||
})
|
||||
}
|
||||
|
||||
granted := scope.Parse(token.Scopes)
|
||||
if scope.Grants(granted, scope.AuthKeys) || scope.Grants(granted, scope.DevicesCore) ||
|
||||
scope.Grants(granted, scope.OAuthKeys) {
|
||||
resp.Tags = strings.Join(token.Tags, " ")
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, resp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,20 +56,9 @@ var apiv2CompatSkipReasons = map[string]string{
|
||||
|
||||
"oauth/O3/0/status": mintScopeRefusalStatus,
|
||||
"oauth/O4/0/scope": unknownScopeGranted,
|
||||
"oauth/O4/0/tags": unknownScopeGranted,
|
||||
|
||||
"oauth/O4/0/tags": mintTagsNotEchoed,
|
||||
"oauth/E1/0/tags": mintTagsNotEchoed,
|
||||
"oauth/E9a/0/tags": mintTagsNotEchoed,
|
||||
"oauth/T1/0/tags": mintTagsNotEchoed,
|
||||
"oauth/D0/6/tags": mintTagsNotEchoed,
|
||||
"oauth/B1/0/tags": mintTagsNotEchoed,
|
||||
"oauth/B3/0/tags": mintTagsNotEchoed,
|
||||
"oauth/B11/1/tags": mintTagsNotEchoed,
|
||||
|
||||
"key-list/setup-token-keys/0/tags": mintTagsNotEchoed,
|
||||
"key-list/setup-token-keys/2/tags": mintTagsNotEchoed,
|
||||
"key-list/setup-token-keys/4/tags": mintTagsNotEchoed,
|
||||
"key-list/setup-token-keys/6/tags": mintTagsNotEchoed,
|
||||
"key-list/setup-token-keys/4/tags": mintTagsSorted,
|
||||
|
||||
"oauth/K5/0/status": unknownKeyType,
|
||||
|
||||
@@ -151,7 +140,7 @@ const (
|
||||
// Differences no planned change removes yet.
|
||||
const (
|
||||
mintScopeRefusalStatus = "TOKEN_SCOPE_REFUSAL_STATUS: SaaS refuses a token scope the client lacks with 403 and a message; headscale with 400 invalid_scope"
|
||||
mintTagsNotEchoed = "TOKEN_TAGS_NOT_ECHOED: SaaS's token answer names the token's tags; headscale's has no tags"
|
||||
mintTagsSorted = "TOKEN_TAGS_SORTED: SaaS's token answer names the tags in the order its client was made with; headscale stores a client's tags sorted"
|
||||
unknownKeyType = "UNKNOWN_KEY_TYPE: SaaS refuses an unknown keyType with 400 before it checks scopes; headscale checks the scope first and answers 403"
|
||||
tagRefusalStatus = "TAG_REFUSAL_STATUS: SaaS refuses a tag outside the token's grant with 400 requested tags are invalid or not permitted; headscale with 403"
|
||||
emptyKeyListNull = "EMPTY_KEY_LIST_NULL: SaaS answers a listing that holds no key with keys null; headscale with []"
|
||||
|
||||
@@ -215,6 +215,15 @@ func TestAPIv2OAuth_TokenEndpoint(t *testing.T) {
|
||||
require.Equalf(t, http.StatusOK, statusDup, "%v", mDup)
|
||||
assert.Equal(t, "auth_keys", mDup["scope"])
|
||||
|
||||
// It names the tags of a token that can assign them; a reader token's
|
||||
// answer has no tags field, whatever its client's tags.
|
||||
assert.Equal(t, "tag:ci", m["tags"])
|
||||
|
||||
_, readerSecret := createClient(t, baseURL, admin, []string{"auth_keys:read"}, []string{"tag:ci"})
|
||||
statusReader, mReader := mintToken(t, baseURL, "", readerSecret, "", false)
|
||||
require.Equalf(t, http.StatusOK, statusReader, "%v", mReader)
|
||||
assert.NotContains(t, mReader, "tags")
|
||||
|
||||
// Bad credentials → RFC 6749 invalid_client.
|
||||
statusBad, mBad := mintToken(t, baseURL, clientID, "hskey-client-deadbeefdead-"+stringOf("0", 64), "", false)
|
||||
assert.Equal(t, http.StatusUnauthorized, statusBad)
|
||||
|
||||
Reference in new issue
Block a user