diff --git a/config.go b/config.go
index 972f76328e701c8126552134d66a4c421135bcb2..b367217dd447f5046e5b7ff6a82064882ebe7244 100644
--- a/config.go
+++ b/config.go
@@ -39,6 +39,11 @@ func newDefaultConfig() *Config {
 		MaxSession:     time.Duration(1) * time.Hour,
 		TagData:        make(map[string]string, 0),
 		ClaimsMatch:    make(map[string]string, 0),
+		CORSConfig: &CORS{
+			Origins: []string{},
+			Methods: []string{},
+			Headers: []string{},
+		},
 	}
 }
 
@@ -209,6 +214,24 @@ func readOptions(cx *cli.Context, config *Config) (err error) {
 			return err
 		}
 	}
+	if cx.IsSet("header") {
+		config.Header, err = decodeKeyPairs(cx.StringSlice("header"))
+		if err != nil {
+			return err
+		}
+	}
+	if cx.IsSet("cors-origins") {
+		config.CORSConfig.Origins = cx.StringSlice("cors-origins")
+	}
+	if cx.IsSet("cors-methods") {
+		config.CORSConfig.Methods = cx.StringSlice("cors-methods")
+	}
+	if cx.IsSet("cors-headers") {
+		config.CORSConfig.Headers = cx.StringSlice("cors-headers")
+	}
+	if cx.IsSet("cors-max-age") {
+		config.CORSConfig.MaxAge = cx.Duration("cors-max-age")
+	}
 	if cx.IsSet("resource") {
 		for _, x := range cx.StringSlice("resource") {
 			resource, err := decodeResource(x)
@@ -327,6 +350,22 @@ func getOptions() []cli.Flag {
 			Usage: "if refresh sessions are enabled we can limit their duration via this",
 			Value: defaults.MaxSession,
 		},
+		cli.StringSliceFlag{
+			Name:  "cors-origins",
+			Usage: "a set of origins to add to the CORS access control (Access-Control-Allow-Origin)",
+		},
+		cli.StringSliceFlag{
+			Name:  "cors-headers",
+			Usage: "a set of headers to add to the CORS access control (Access-Control-Allow-Headers)",
+		},
+		cli.StringSliceFlag{
+			Name:  "cors-methods",
+			Usage: "the method permitted in the access control (Access-Control-Allow-Methods)",
+		},
+		cli.DurationFlag{
+			Name:  "cors-max-age",
+			Usage: "the max age applied to cors headers (Access-Control-Max-Age)",
+		},
 		cli.BoolFlag{
 			Name:  "skip-token-verification",
 			Usage: "testing purposes ONLY, the option allows you to bypass the token verification, expiration and roles are still enforced",
diff --git a/doc.go b/doc.go
index 81bc3498c621f7a513e8f70177d6c17d2029f72b..fe5b679b359f3aec45755fdf55ce4ed43b28ebf7 100644
--- a/doc.go
+++ b/doc.go
@@ -67,6 +67,18 @@ type Resource struct {
 	Roles []string `json:"roles" yaml:"roles"`
 }
 
+// CORS controls
+type CORS struct {
+	// Origins is a list of origins permitted
+	Origins []string `json:"origins" yaml:"origins"`
+	// Methods is a set of access control methods
+	Methods []string `json:"methods" yaml:"methods"`
+	// Headers is a set of cors headers
+	Headers []string `json:"headers" yaml:"headers"`
+	// MaxAge is the age for CORS
+	MaxAge time.Duration `json:"max-age" yaml:"max-age"`
+}
+
 // Config is the configuration for the proxy
 type Config struct {
 	// LogRequests indicates if we should log all the requests
@@ -103,6 +115,10 @@ type Config struct {
 	Upstream string `json:"upstream" yaml:"upstream"`
 	// TagData is passed to the templates
 	TagData map[string]string `json:"TagData" yaml:"TagData"`
+	// CORS permits adding headers to the /oauth handlers
+	CORSConfig *CORS `json:"cors" yaml:"cors"`
+	// Header permits adding customs headers across the board
+	Header map[string]string `json:"headers" yaml:"headers"`
 	// Scopes is a list of scope we should request
 	Scopes []string `json:"scopes" yaml:"scopes"`
 	// Resources is a list of protected resources
diff --git a/handlers.go b/handlers.go
index 8dc8c0b8396104c367bf2610100ce6d8b59fcd35..a469019ac8d18b6c6fc2603ceb69c81946ae7c91 100644
--- a/handlers.go
+++ b/handlers.go
@@ -22,6 +22,7 @@ import (
 	"strings"
 	"time"
 
+	"fmt"
 	log "github.com/Sirupsen/logrus"
 	"github.com/gambol99/go-oidc/jose"
 	"github.com/gambol99/go-oidc/oauth2"
@@ -113,6 +114,11 @@ func (r *KeycloakProxy) entryPointHandler() gin.HandlerFunc {
 		// step: pass into the authentication and admission handlers
 		cx.Next()
 
+		// step: add a custom headers to the request
+		for k, v := range r.config.Header {
+			cx.Request.Header.Set(k, v)
+		}
+
 		// step: check the request has not been aborted and if not, proxy request
 		if !cx.IsAborted() {
 			r.proxyHandler(cx)
@@ -446,6 +452,9 @@ func (r *KeycloakProxy) oauthAuthorizationHandler(cx *gin.Context) {
 		return
 	}
 
+	// step: add the cors headers
+	r.corsAccessHeaders(cx)
+
 	// step: get the redirection url
 	r.redirectToURL(redirectionURL, cx)
 }
@@ -555,6 +564,9 @@ func (r *KeycloakProxy) oauthCallbackHandler(cx *gin.Context) {
 		}
 	}
 
+	// step: add the cors headers
+	r.corsAccessHeaders(cx)
+
 	r.redirectToURL(state, cx)
 }
 
@@ -564,3 +576,21 @@ func (r *KeycloakProxy) oauthCallbackHandler(cx *gin.Context) {
 func (r *KeycloakProxy) healthHandler(cx *gin.Context) {
 	cx.String(http.StatusOK, "OK")
 }
+
+// corsAccessHeaders adds the cors access controls to the oauth responses
+func (r *KeycloakProxy) corsAccessHeaders(cx *gin.Context) {
+	cors := r.config.CORSConfig
+	if len(cors.Origins) > 0 {
+		cx.Writer.Header().Set("Access-Control-Allow-Origin", strings.Join(cors.Origins, ","))
+	}
+	if len(cors.Methods) > 0 {
+		cx.Writer.Header().Set("Access-Control-Allow-Methods", strings.Join(cors.Methods, ","))
+	}
+	if len(cors.Headers) > 0 {
+		cx.Writer.Header().Set("Access-Control-Allow-Headers", strings.Join(cors.Headers, ","))
+	}
+	if cors.MaxAge > 0 {
+		cx.Writer.Header().Set("Access-Control-Max-Age",
+			fmt.Sprintf("%d", int(cors.MaxAge.Seconds())))
+	}
+}
diff --git a/oauth.yml b/oauth.yml
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/oauth_test.go b/oauth_test.go
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000