Commit c917c94d authored by Sietse Ringers's avatar Sietse Ringers
Browse files

feat: make myirmaserver CORS origin header configurable

parent f1307f0b
......@@ -41,6 +41,7 @@ func init() {
flags.IntP("port", "p", 8080, "port at which to listen")
flags.StringP("listen-addr", "l", "", "address at which to listen (default 0.0.0.0)")
flags.StringSlice("cors-allowed-origins", nil, "CORS allowed origins")
flags.Lookup("port").Header = `Server address and port to listen on`
flags.String("db-type", myirmaserver.DatabaseTypePostgres, "Type of database to connect keyshare server to")
......@@ -90,6 +91,8 @@ func configureMyirmad(cmd *cobra.Command) *myirmaserver.Configuration {
Configuration: configureIRMAServer(),
EmailConfiguration: configureEmail(),
CORSAllowedOrigins: viper.GetStringSlice("cors-allowed-origins"),
StaticPath: viper.GetString("static-path"),
StaticPrefix: viper.GetString("static-prefix"),
......
......@@ -2,6 +2,7 @@ package myirmaserver
import (
"html/template"
"net/url"
"strings"
"github.com/go-errors/errors"
......@@ -27,6 +28,8 @@ type Configuration struct {
// IRMA server configuration. If not given, this will be populated using information here
*server.Configuration `mapstructure:",squash"`
CORSAllowedOrigins []string `json:"cors_allowed_origins" mapstructure:"cors_allowed_origins"`
// Path to static content to serve (for testing)
StaticPath string `json:"static_path" mapstructure:"static_path"`
StaticPrefix string `json:"static_prefix" mapstructure:"static_prefix"`
......@@ -147,5 +150,22 @@ func processConfiguration(conf *Configuration) error {
}
conf.URL += "irma/"
for _, origin := range conf.CORSAllowedOrigins {
if origin == "*" {
if len(conf.CORSAllowedOrigins) != 1 {
return server.LogError(errors.New("CORS allowed origin * cannot be specified together with other allowed origins"))
}
continue
}
u, err := url.Parse(origin)
if err != nil {
return server.LogError(errors.Errorf(`Invalid CORS allowed origin "%s": %v`, origin, err))
}
if !strings.HasPrefix(u.Scheme, "http") || u.Path != "" || u.RawQuery != "" || u.RawFragment != "" {
err = errors.Errorf(`Invalid CORS allowed origin "%s": must start with http(s) but be without path, query or fragment`, origin)
return server.LogError(err)
}
}
return nil
}
......@@ -57,4 +57,29 @@ func TestConfValidation(t *testing.T) {
conf.KeyshareAttributes = append(conf.EmailAttributes, irma.NewAttributeTypeIdentifier("test.test.foo.bar"))
_, err = New(conf)
assert.Error(t, err)
conf = validConf(t)
conf.CORSAllowedOrigins = []string{"*"}
_, err = New(conf)
assert.NoError(t, err)
conf = validConf(t)
conf.CORSAllowedOrigins = []string{"http://example.com"}
_, err = New(conf)
assert.NoError(t, err)
conf = validConf(t)
conf.CORSAllowedOrigins = []string{"*", "http://example.com"}
_, err = New(conf)
assert.Error(t, err)
conf = validConf(t)
conf.CORSAllowedOrigins = []string{"example.com"}
_, err = New(conf)
assert.Error(t, err)
conf = validConf(t)
conf.CORSAllowedOrigins = []string{"http://example.com/foobar"}
_, err = New(conf)
assert.Error(t, err)
}
......@@ -32,13 +32,6 @@ type Server struct {
var (
ErrInvalidEmail = errors.New("Email not associated with account")
corsOptions = cors.Options{
AllowedOrigins: []string{"*"}, // TODO make this configurable
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "Cache-Control"},
AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete},
AllowCredentials: true,
}
)
func New(conf *Configuration) (*Server, error) {
......@@ -80,7 +73,12 @@ func (s *Server) Stop() {
func (s *Server) Handler() http.Handler {
router := chi.NewRouter()
router.Use(cors.New(corsOptions).Handler)
router.Use(cors.New(cors.Options{
AllowedOrigins: s.conf.CORSAllowedOrigins,
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "Cache-Control"},
AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete},
AllowCredentials: true,
}).Handler)
router.Group(func(router chi.Router) {
router.Use(server.SizeLimitMiddleware)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment