mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-13 03:42:35 -06:00
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:
@@ -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``.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user