Implemented OIDC Bearer middleware (#188)

* Implemented OIDC Bearer middleware

* Fixed indentation
Added support for case-insensitive scheme
Moved scheme to constant

Co-authored-by: Aman Bhardwaj <amanbha@users.noreply.github.com>
This commit is contained in:
Marcin Kosieradzki 2020-01-16 22:26:30 +01:00 committed by Aman Bhardwaj
parent e5fbb7e825
commit 381777dc3b
3 changed files with 95 additions and 0 deletions

3
go.mod
View File

@ -28,6 +28,7 @@ require (
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/coreos/bbolt v1.3.3 // indirect
github.com/coreos/etcd v3.3.17+incompatible // indirect
github.com/coreos/go-oidc v2.1.0+incompatible
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
@ -72,6 +73,7 @@ require (
github.com/onsi/gomega v1.7.0 // indirect
github.com/openzipkin/zipkin-go v0.1.6
github.com/pkg/errors v0.8.1
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/prometheus/client_golang v1.2.1 // indirect
github.com/russross/blackfriday v2.0.0+incompatible // indirect
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da
@ -113,6 +115,7 @@ require (
gopkg.in/jcmturner/goidentity.v3 v3.0.0 // indirect
gopkg.in/jcmturner/gokrb5.v7 v7.3.0 // indirect
gopkg.in/kataras/go-serializer.v0 v0.0.4 // indirect
gopkg.in/square/go-jose.v2 v2.4.1 // indirect
k8s.io/apimachinery v0.0.0-20190817020851-f2f3a405f61d
k8s.io/client v0.0.0-00010101000000-000000000000 // indirect
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab

6
go.sum
View File

@ -121,6 +121,8 @@ github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY=
github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.17+incompatible h1:f/Z3EoDSx1yjaIjLQGo1diYUlQYSBrrAQ5vP8NjwXwo=
github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM=
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c=
@ -421,6 +423,8 @@ github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6J
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@ -716,6 +720,8 @@ gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLv
gopkg.in/kataras/go-serializer.v0 v0.0.4 h1:mVy3gjU4zZZBe+8JbZDRTMPJdrB0lzBNsLLREBcKGgU=
gopkg.in/kataras/go-serializer.v0 v0.0.4/go.mod h1:v2jHg/3Wp7uncDNzenTsX75PRDxhzlxoo/qDvM4ZGxk=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y=
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=

View File

@ -0,0 +1,86 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// ------------------------------------------------------------
package bearer
import (
"encoding/json"
"context"
"strings"
"github.com/dapr/components-contrib/middleware"
oidc "github.com/coreos/go-oidc"
"github.com/valyala/fasthttp"
)
type bearerMiddlewareMetadata struct {
IssuerURL string `json:"issuerURL"`
ClientID string `json:"clientID"`
}
// NewBearerMiddleware returns a new oAuth2 middleware
func NewBearerMiddleware() *Middleware {
return &Middleware{}
}
// Middleware is an oAuth2 authentication middleware
type Middleware struct {
}
const (
bearerPrefix = "bearer "
bearerPrefixLength = len(bearerPrefix)
)
// GetHandler retruns the HTTP handler provided by the middleware
func (m *Middleware) GetHandler(metadata middleware.Metadata) (func(h fasthttp.RequestHandler) fasthttp.RequestHandler, error) {
meta, err := m.getNativeMetadata(metadata)
if err != nil {
return nil, err
}
provider, err := oidc.NewProvider(context.Background(), meta.IssuerURL)
if err != nil {
return nil, err
}
verifier := provider.Verifier(&oidc.Config{
ClientID: meta.ClientID,
})
return func(h fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
authHeader := string(ctx.Request.Header.Peek(fasthttp.HeaderAuthorization))
if (!strings.HasPrefix(strings.ToLower(authHeader), bearerPrefix)) {
ctx.Error(fasthttp.StatusMessage(fasthttp.StatusUnauthorized), fasthttp.StatusUnauthorized)
return
}
rawToken := authHeader[bearerPrefixLength:]
_, err := verifier.Verify(ctx, rawToken)
if (err != nil) {
ctx.Error(fasthttp.StatusMessage(fasthttp.StatusUnauthorized), fasthttp.StatusUnauthorized)
return
}
h(ctx)
}
}, nil
}
func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*bearerMiddlewareMetadata, error) {
b, err := json.Marshal(metadata.Properties)
if err != nil {
return nil, err
}
var middlewareMetadata bearerMiddlewareMetadata
err = json.Unmarshal(b, &middlewareMetadata)
if err != nil {
return nil, err
}
return &middlewareMetadata, nil
}