Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OIDC/OAuth2 authentication support #3

Merged
merged 6 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/server/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ func NewServer(ctx context.Context, conf config.Config, log *logger.Logger) (*Se
RPCAddress: ":" + conf.Server.RPCPort,
HTTPPort: conf.Server.HTTPPort,
BasicAuth: conf.Server.BasicAuth,
OidcAuth: conf.Server.OidcAuth,
DisableHTTPCache: conf.Server.DisableHTTPCache,
Log: log,
Tasks: &server.TaskService{
Expand Down
30 changes: 30 additions & 0 deletions cmd/util/config.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package util

import (
"fmt"
"io/ioutil"
"math/rand"
"os"
"path/filepath"

Expand Down Expand Up @@ -34,6 +36,24 @@ func MergeConfigFileWithFlags(file string, flagConf config.Config) (config.Confi
}
}

// Make sure that User/Password are defined for conf.RPCClient:
// 1) when conf.Server.BasicAuth has credentials
// 2) when conf.Server.OidcAuth is enabled (clients still need to provide Basic credentials)
if conf.RPCClient.User == "" && conf.RPCClient.Password == "" {
if len(conf.Server.BasicAuth) > 0 {
fmt.Println("Configuration problem: RPCClient User and Password " +
"are undefined while Server.BasicAuth is enforced.")
os.Exit(1)
} else if conf.Server.OidcAuth.ServiceConfigUrl != "" {
// Generating random user/password credentials for RPC:
conf.RPCClient.User = randomCredential()
conf.RPCClient.Password = randomCredential()
conf.Server.BasicAuth = append(conf.Server.BasicAuth, config.BasicCredential{
User: conf.RPCClient.User,
Password: conf.RPCClient.Password,
})
}
}
return conf, nil
}

Expand All @@ -58,3 +78,13 @@ func TempConfigFile(c config.Config, name string) (path string, cleanup func())
}
return p, cleanup
}

// RandomString generates a random string of length 20.
func randomCredential() string {
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
b := make([]rune, 20)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
10 changes: 9 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ type BasicCredential struct {
Password string
}

type OidcAuth struct {
ServiceConfigUrl string
ClientId string
ClientSecret string
RequireScope string
RequireAudience string
}

// RPCClient describes configuration for gRPC clients
type RPCClient struct {
BasicCredential
Expand All @@ -77,6 +85,7 @@ type Server struct {
HTTPPort string
RPCPort string
BasicAuth []BasicCredential
OidcAuth OidcAuth
DisableHTTPCache bool
}

Expand Down Expand Up @@ -395,7 +404,6 @@ func (h HTSGETStorage) Valid() bool {
return !h.Disabled
}


// Kubernetes describes the configuration for the Kubernetes compute backend.
type Kubernetes struct {
// The executor used to execute tasks. Available executors: docker, kubernetes
Expand Down
14 changes: 14 additions & 0 deletions config/default-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ Server:
# - User: user2
# Password: foobar

# Require Bearer JWT authentication for the server APIs.
# Server won't launch when configuration URL cannot be loaded.
# OidcAuth:
# # URL of the OIDC service configuration:
# ServiceConfigUrl: ""
# # Client ID and secret are sent with the token introspection request
# # (Basic authentication):
# ClientId:
# ClientSecret:
# # Optional: if specified, this scope value must be in the token:
# RequireScope:
# # Optional: if specified, this audience value must be in the token:
# RequireAudience:

# Include a "Cache-Control: no-store" HTTP header in Get/List responses
# to prevent caching by intermediary services.
DisableHTTPCache: true
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ require (
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/kr/pretty v0.3.1
github.com/lestrrat-go/jwx/v2 v2.0.19 // indirect
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381
github.com/maruel/panicparse v1.3.0 // indirect
github.com/mattn/go-runewidth v0.0.8 // indirect
Expand All @@ -59,8 +60,8 @@ require (
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.3
golang.org/x/crypto v0.14.0
github.com/stretchr/testify v1.8.4
golang.org/x/crypto v0.17.0
golang.org/x/net v0.17.0
golang.org/x/oauth2 v0.8.0
golang.org/x/time v0.3.0
Expand Down
30 changes: 30 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,9 @@ github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/dgraph-io/badger/v2 v2.0.1 h1:+D6dhIqC6jIeCclnxMHqk4HPuXgrRN5UfBsLR4dNQ3A=
github.com/dgraph-io/badger/v2 v2.0.1/go.mod h1:YoRSIp1LmAJ7zH7tZwRvjNMUYLxB4wl3ebYkaIruZ04=
github.com/dgraph-io/ristretto v0.0.0-20191025175511-c1f00be0418e h1:aeUNgwup7PnDOBAD1BOKAqzb/W/NksOj6r3dwKKuqfg=
Expand Down Expand Up @@ -801,6 +804,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4
github.com/go-test/deep v1.0.5 h1:AKODKU3pDH1RzZzm6YZu77YWtEAq6uh1rLIAQlay2qc=
github.com/go-test/deep v1.0.5/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
Expand Down Expand Up @@ -995,6 +1000,19 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8=
github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
github.com/lestrrat-go/jwx/v2 v2.0.19 h1:ekv1qEZE6BVct89QA+pRF6+4pCpfVrOnEJnTnT4RXoY=
github.com/lestrrat-go/jwx/v2 v2.0.19/go.mod h1:l3im3coce1lL2cDeAjqmaR+Awx+X8Ih+2k8BuHNJ4CU=
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
Expand Down Expand Up @@ -1142,6 +1160,8 @@ github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNue
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v2.20.1+incompatible h1:oIq9Cq4i84Hk8uQAUOG3eNdI/29hBawGrD5YRl6JRDY=
Expand Down Expand Up @@ -1194,6 +1214,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
Expand Down Expand Up @@ -1237,6 +1259,8 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
Expand Down Expand Up @@ -1509,6 +1533,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
Expand All @@ -1521,6 +1547,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand All @@ -1539,6 +1567,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
98 changes: 46 additions & 52 deletions server/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,77 +9,71 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
)

// Return a new interceptor function that authorizes RPCs
// using a password stored in the config.
func newAuthInterceptor(creds []config.BasicCredential) grpc.UnaryServerInterceptor {
var (
errMissingMetadata = status.Errorf(codes.InvalidArgument, "Missing metadata in the context")
errTokenRequired = status.Errorf(codes.Unauthenticated, "Basic/Bearer authorization token missing")
errInvalidBasicToken = status.Errorf(codes.Unauthenticated, "Invalid Basic authorization token")
errInvalidBearerToken = status.Errorf(codes.Unauthenticated, "Invalid Bearer authorization token")
)

// Return a new interceptor function that authorizes RPCs.
func newAuthInterceptor(creds []config.BasicCredential, oidc config.OidcAuth) grpc.UnaryServerInterceptor {
basicCreds := initBasicCredsMap(creds)
oidcConfig := initOidcConfig(oidc)
requireAuth := len(basicCreds) > 0 || oidcConfig != nil

// Return a function that is the interceptor.
return func(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler) (interface{}, error) {
var authorized bool
var err error
for _, cred := range creds {
err = authorize(ctx, cred.User, cred.Password)
if err == nil {
authorized = true
}
}
if len(creds) == 0 {
authorized = true
}
if !authorized {
return nil, err

if !requireAuth {
return handler(ctx, req)
}
return handler(ctx, req)
}
}

// Check the context's metadata for the configured server/API password.
func authorize(ctx context.Context, user, password string) error {
if md, ok := metadata.FromIncomingContext(ctx); ok {
if len(md["authorization"]) > 0 {
raw := md["authorization"][0]
requser, reqpass, ok := parseBasicAuth(raw)
if ok {
if requser == user && reqpass == password {
return nil
}
return grpc.Errorf(codes.PermissionDenied, "")
}
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return nil, errMissingMetadata
}
}

return grpc.Errorf(codes.Unauthenticated, "")
}
values := md["authorization"]
if len(values) < 1 {
return nil, errTokenRequired
}

// parseBasicAuth parses an HTTP Basic Authentication string.
// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true).
//
// Taken from Go core: https://golang.org/src/net/http/request.go?s=27379:27445#L828
func parseBasicAuth(auth string) (username, password string, ok bool) {
const prefix = "Basic "
authorized := false
auth_err := errTokenRequired

if !strings.HasPrefix(auth, prefix) {
return
}
if strings.HasPrefix(values[0], "Basic ") {
auth_err = errInvalidBasicToken
authorized = basicCreds[values[0]]
} else if oidcConfig != nil && strings.HasPrefix(values[0], "Bearer ") {
auth_err = errInvalidBearerToken
jwtString := strings.TrimPrefix(values[0], "Bearer ")
jwt := oidcConfig.ParseJwt(jwtString)
authorized = jwt != nil
}

c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
if !authorized {
return nil, auth_err
}

if err != nil {
return
return handler(ctx, req)
}
}

cs := string(c)
s := strings.IndexByte(cs, ':')

if s < 0 {
return
func initBasicCredsMap(creds []config.BasicCredential) map[string]bool {
basicCreds := make(map[string]bool)
for _, cred := range creds {
credBytes := []byte(cred.User + ":" + cred.Password)
fullValue := "Basic " + base64.StdEncoding.EncodeToString(credBytes)
basicCreds[fullValue] = true
}

return cs[:s], cs[s+1:], true
return basicCreds
}
Loading
Loading