Add HTTP auth check (#128)

* Add HTTP auth check

Signed-off-by: Drasko DRASKOVIC <drasko.draskovic@gmail.com>

* Add HTTP auth via Manager Client

Signed-off-by: Drasko DRASKOVIC <drasko.draskovic@gmail.com>

* Change the way manager client is injected

Instead of relying on modifying service structure, manager client is
injected through handler factory method, and store as a variable in that
module.

Signed-off-by: Dejan Mijic <dejan@mainflux.com>

* Update dockerignore

Signed-off-by: Dejan Mijic <dejan@mainflux.com>
This commit is contained in:
Drasko DRASKOVIC
2018-01-07 14:42:38 +01:00
committed by Dejan Mijić
parent d413508b25
commit 4f467dcdde
5 changed files with 40 additions and 21 deletions
+1 -2
View File
@@ -1,9 +1,8 @@
.git/
.github/
bin/
docker/
glide.lock
glide.yaml
LICENSE
MAINTAINERS
README.md
swagger.yml
+1
View File
@@ -74,3 +74,4 @@ services:
- mainflux-nats:nats
environment:
- HTTP_ADAPTER_NATS_URL=nats://nats:4222
- HTTP_ADAPTER_MANAGER_URL=http://manager:8180
+14 -8
View File
@@ -12,25 +12,30 @@ import (
adapter "github.com/mainflux/mainflux/http"
"github.com/mainflux/mainflux/http/api"
"github.com/mainflux/mainflux/http/nats"
manager "github.com/mainflux/mainflux/manager/client"
broker "github.com/nats-io/go-nats"
stdprometheus "github.com/prometheus/client_golang/prometheus"
)
const (
port int = 7070
defNatsURL string = broker.DefaultURL
envNatsURL string = "HTTP_ADAPTER_NATS_URL"
port int = 7070
defNatsURL string = broker.DefaultURL
envNatsURL string = "HTTP_ADAPTER_NATS_URL"
defManagerURL string = "http://localhost:8180"
envManagerURL string = "HTTP_ADAPTER_MANAGER_URL"
)
type config struct {
Port int
NatsURL string
Port int
NatsURL string
ManagerURL string
}
func main() {
cfg := config{
Port: port,
NatsURL: getenv(envNatsURL, defNatsURL),
Port: port,
NatsURL: getenv(envNatsURL, defNatsURL),
ManagerURL: getenv(envManagerURL, defManagerURL),
}
logger := log.NewJSONLogger(log.NewSyncWriter(os.Stdout))
@@ -69,7 +74,8 @@ func main() {
go func() {
p := fmt.Sprintf(":%d", cfg.Port)
errs <- http.ListenAndServe(p, api.MakeHandler(svc))
mc := manager.NewClient(cfg.ManagerURL)
errs <- http.ListenAndServe(p, api.MakeHandler(svc, mc))
}()
go func() {
+18 -5
View File
@@ -6,11 +6,13 @@ import (
"io"
"io/ioutil"
"net/http"
"strings"
kithttp "github.com/go-kit/kit/transport/http"
"github.com/go-zoo/bone"
"github.com/mainflux/mainflux"
adapter "github.com/mainflux/mainflux/http"
manager "github.com/mainflux/mainflux/manager/client"
"github.com/mainflux/mainflux/writer"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
@@ -24,10 +26,13 @@ var (
errMalformedData error = errors.New("malformed SenML data")
errUnknownType error = errors.New("unknown content type")
errUnauthorizedAccess error = errors.New("missing or invalid credentials provided")
auth manager.ManagerClient
)
// MakeHandler returns a HTTP handler for API endpoints.
func MakeHandler(svc adapter.Service) http.Handler {
func MakeHandler(svc adapter.Service, mc manager.ManagerClient) http.Handler {
auth = mc
opts := []kithttp.ServerOption{
kithttp.ServerErrorEncoder(encodeError),
}
@@ -76,14 +81,22 @@ func decodeRequest(_ context.Context, r *http.Request) (interface{}, error) {
return msg, nil
}
// TODO: contact an auth provider
func authorize(r *http.Request) (string, error) {
var apiKey string
if apiKey = r.Header.Get("Authorization"); apiKey == "" {
apiKey := r.Header.Get("Authorization")
if apiKey == "" {
return "", errUnauthorizedAccess
}
return apiKey, nil
// Path is `/channels/:id/messages`, we need chanID.
c := strings.Split(r.URL.Path, "/")[2]
id, err := auth.CanAccess(c, apiKey)
if err != nil {
return "", err
}
return id, nil
}
func checkContentType(r *http.Request) (string, error) {
+6 -6
View File
@@ -21,13 +21,13 @@ const (
// ErrServiceUnreachable indicates that the service instance is not available.
var ErrServiceUnreachable = errors.New("manager service unavailable")
type managerClient struct {
type ManagerClient struct {
url string
cb *gobreaker.CircuitBreaker
}
// NewClient instantiates the manager service client given its base URL.
func NewClient(url string) managerClient {
func NewClient(url string) ManagerClient {
st := gobreaker.Settings{
Name: "Manager",
ReadyToTrip: func(counts gobreaker.Counts) bool {
@@ -36,7 +36,7 @@ func NewClient(url string) managerClient {
},
}
mc := managerClient{
mc := ManagerClient{
url: url,
cb: gobreaker.NewCircuitBreaker(st),
}
@@ -44,17 +44,17 @@ func NewClient(url string) managerClient {
return mc
}
func (mc managerClient) VerifyToken(token string) (string, error) {
func (mc ManagerClient) VerifyToken(token string) (string, error) {
url := fmt.Sprintf("%s/access-grant", mc.url)
return mc.makeRequest(url, token)
}
func (mc managerClient) CanAccess(channel, token string) (string, error) {
func (mc ManagerClient) CanAccess(channel, token string) (string, error) {
url := fmt.Sprintf("%s/channels/%s/access-grant", mc.url, channel)
return mc.makeRequest(url, token)
}
func (mc managerClient) makeRequest(url, token string) (string, error) {
func (mc ManagerClient) makeRequest(url, token string) (string, error) {
response, err := mc.cb.Execute(func() (interface{}, error) {
hc := &http.Client{
Timeout: timeout,