Improve token authentication docs and handler

With these changes, the identity will be undefined if a token is not
specified. This is less surprising than the empty string that would be
set prior to these changes.

Fixes #901

Signed-off-by: Torin Sandall <torinsandall@gmail.com>
This commit is contained in:
Torin Sandall
2018-09-04 10:34:11 -07:00
parent cc22d5219a
commit 4aa9d715e4
4 changed files with 28 additions and 13 deletions
+7 -1
View File
@@ -82,7 +82,13 @@ default to `off`.
For authentication, OPA supports:
- [Bearer tokens](/rest-api.md#bearer-tokens): Bearer tokens are enabled by starting OPA with ``--authentication=token``.
- [Bearer tokens](/rest-api.md#bearer-tokens): Bearer tokens are enabled by
starting OPA with ``--authentication=token``. When the `token` authentication
mode is enabled, OPA will extract the Bearer token from incoming API requests
and provide to the authorization handler. When you use the `token`
authentication, you must configure an authorization policy that checks the
tokens. If the client does not supply a Bearer token, the `input.identity`
value will be undefined when the authorization policy is evaluated.
For authorization, OPA relies on policy written in Rego. Authorization is
enabled by starting OPA with ``--authorization=basic``.
+8 -5
View File
@@ -85,14 +85,17 @@ func makeInput(r *http.Request) (interface{}, error) {
}
method := strings.ToUpper(r.Method)
identity := identifier.Identity(r)
query := r.URL.Query()
input := map[string]interface{}{
"path": path,
"method": method,
"identity": identity,
"params": query,
"path": path,
"method": method,
"params": query,
}
identity, ok := identifier.Identity(r)
if ok {
input["identity"] = identity
}
return input, nil
+3 -3
View File
@@ -12,13 +12,13 @@ import (
)
// Identity returns the identity of the caller associated with ctx.
func Identity(r *http.Request) string {
func Identity(r *http.Request) (string, bool) {
ctx := r.Context()
v, ok := ctx.Value(identity).(string)
if ok {
return v
return v, true
}
return ""
return "", false
}
// SetIdentity returns a new http.Request with the identity set to v.
+10 -4
View File
@@ -11,10 +11,11 @@ import (
type mockHandler struct {
identity string
defined bool
}
func (h *mockHandler) ServeHTTP(_ http.ResponseWriter, r *http.Request) {
h.identity = Identity(r)
h.identity, h.defined = Identity(r)
}
func TestTokenBased(t *testing.T) {
@@ -30,10 +31,11 @@ func TestTokenBased(t *testing.T) {
tests := []struct {
value string
expected string
defined bool
}{
{"", ""},
{"Bearer this-is-the-token", "this-is-the-token"},
{"Bearer this-is-the-token-with-spaces", "this-is-the-token-with-spaces"},
{"", "", false},
{"Bearer this-is-the-token", "this-is-the-token", true},
{"Bearer this-is-the-token-with-spaces", "this-is-the-token-with-spaces", true},
}
for _, tc := range tests {
@@ -44,6 +46,10 @@ func TestTokenBased(t *testing.T) {
handler.ServeHTTP(nil, req)
if mock.defined != tc.defined {
t.Fatalf("Expected defined to be %v but got: %v", tc.defined, mock.defined)
}
if mock.identity != tc.expected {
t.Fatalf("Expected identity to be %s but got: %s", tc.expected, mock.identity)
}