add nonce endpoint
This commit is contained in:
parent
364de7114a
commit
d6f5027480
112
mockid.go
112
mockid.go
|
@ -34,8 +34,13 @@ type PublicJWK struct {
|
||||||
Y string `json:"y"`
|
Y string `json:"y"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var nonces map[string]int64
|
||||||
var jwksPrefix string
|
var jwksPrefix string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
nonces = make(map[string]int64)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
var port int
|
var port int
|
||||||
|
@ -92,6 +97,34 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
http.HandleFunc("/api/new-nonce", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
baseURL := getBaseURL(r)
|
||||||
|
/*
|
||||||
|
res.statusCode = 200;
|
||||||
|
res.setHeader("Cache-Control", "max-age=0, no-cache, no-store");
|
||||||
|
// TODO
|
||||||
|
//res.setHeader("Date", "Sun, 10 Mar 2019 08:04:45 GMT");
|
||||||
|
// is this the expiration of the nonce itself? methinks maybe so
|
||||||
|
//res.setHeader("Expires", "Sun, 10 Mar 2019 08:04:45 GMT");
|
||||||
|
// TODO use one of the registered domains
|
||||||
|
//var indexUrl = "https://acme-staging-v02.api.letsencrypt.org/index"
|
||||||
|
*/
|
||||||
|
//var port = (state.config.ipc && state.config.ipc.port || state._ipc.port || undefined);
|
||||||
|
//var indexUrl = "http://localhost:" + port + "/index";
|
||||||
|
indexUrl := baseURL + "/index";
|
||||||
|
w.Header().Set("Link", "<" + indexUrl + ">;rel=\"index\"");
|
||||||
|
w.Header().Set("Cache-Control", "max-age=0, no-cache, no-store");
|
||||||
|
w.Header().Set("Pragma", "no-cache");
|
||||||
|
//res.setHeader("Strict-Transport-Security", "max-age=604800");
|
||||||
|
|
||||||
|
w.Header().Set("X-Frame-Options", "DENY")
|
||||||
|
issueNonce(w, r)
|
||||||
|
})
|
||||||
|
|
||||||
|
http.HandleFunc("/api/new-account", requireNonce(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Error(w, "Not Implemented", http.StatusNotImplemented)
|
||||||
|
}))
|
||||||
|
|
||||||
http.HandleFunc("/api/jwks", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/api/jwks", func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Printf("%s %s %s", r.Method, r.Host, r.URL.Path)
|
log.Printf("%s %s %s", r.Method, r.Host, r.URL.Path)
|
||||||
if "POST" != r.Method {
|
if "POST" != r.Method {
|
||||||
|
@ -185,37 +218,20 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var scheme string
|
baseURL := getBaseURL(r)
|
||||||
if nil != r.TLS || "https" == r.Header.Get("X-Forwarded-Proto") {
|
|
||||||
scheme = "https://"
|
|
||||||
} else {
|
|
||||||
scheme = "http://"
|
|
||||||
}
|
|
||||||
w.Write([]byte(fmt.Sprintf(
|
w.Write([]byte(fmt.Sprintf(
|
||||||
`{ "iss":%q, "jwks_url":%q }`, scheme+r.Host+"/", scheme+r.Host+"/.well-known/jwks.json",
|
`{ "iss":%q, "jwks_url":%q }`, baseURL+"/", baseURL+"/.well-known/jwks.json",
|
||||||
)))
|
)))
|
||||||
})
|
})
|
||||||
|
|
||||||
http.HandleFunc("/access_token", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/access_token", func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Printf("%s %s\n", r.Method, r.URL.Path)
|
log.Printf("%s %s\n", r.Method, r.URL.Path)
|
||||||
var scheme string
|
_, _, token := genToken(getBaseURL(r), priv, r.URL.Query())
|
||||||
if nil != r.TLS || "https" == r.Header.Get("X-Forwarded-Proto") {
|
|
||||||
scheme = "https://"
|
|
||||||
} else {
|
|
||||||
scheme = "http://"
|
|
||||||
}
|
|
||||||
_, _, token := genToken(scheme+r.Host, priv, r.URL.Query())
|
|
||||||
fmt.Fprintf(w, token)
|
fmt.Fprintf(w, token)
|
||||||
})
|
})
|
||||||
|
|
||||||
http.HandleFunc("/authorization_header", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/authorization_header", func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Printf("%s %s\n", r.Method, r.URL.Path)
|
log.Printf("%s %s\n", r.Method, r.URL.Path)
|
||||||
var scheme string
|
|
||||||
if nil != r.TLS || "https" == r.Header.Get("X-Forwarded-Proto") {
|
|
||||||
scheme = "https://"
|
|
||||||
} else {
|
|
||||||
scheme = "http://"
|
|
||||||
}
|
|
||||||
|
|
||||||
var header string
|
var header string
|
||||||
headers, _ := r.URL.Query()["header"]
|
headers, _ := r.URL.Query()["header"]
|
||||||
|
@ -233,7 +249,7 @@ func main() {
|
||||||
prefix = prefixes[0]
|
prefix = prefixes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, token := genToken(scheme+r.Host, priv, r.URL.Query())
|
_, _, token := genToken(getBaseURL(r), priv, r.URL.Query())
|
||||||
fmt.Fprintf(w, "%s: %s%s", header, prefix, token)
|
fmt.Fprintf(w, "%s: %s%s", header, prefix, token)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -243,14 +259,9 @@ func main() {
|
||||||
})
|
})
|
||||||
|
|
||||||
http.HandleFunc("/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) {
|
||||||
var scheme string
|
baseURL := getBaseURL(r)
|
||||||
if nil != r.TLS || "https" == r.Header.Get("X-Forwarded-Proto") {
|
|
||||||
scheme = "https://"
|
|
||||||
} else {
|
|
||||||
scheme = "http://"
|
|
||||||
}
|
|
||||||
log.Printf("%s %s\n", r.Method, r.URL.Path)
|
log.Printf("%s %s\n", r.Method, r.URL.Path)
|
||||||
fmt.Fprintf(w, `{ "issuer": "%s", "jwks_uri": "%s/.well-known/jwks.json" }`, scheme+r.Host, scheme+r.Host)
|
fmt.Fprintf(w, `{ "issuer": "%s", "jwks_uri": "%s/.well-known/jwks.json" }`, baseURL, baseURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
http.HandleFunc("/.well-known/jwks.json", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/.well-known/jwks.json", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -407,3 +418,48 @@ func thumbprintKey(pub *ecdsa.PublicKey) string {
|
||||||
sha := sha256.Sum256(minpub)
|
sha := sha256.Sum256(minpub)
|
||||||
return base64.RawURLEncoding.EncodeToString(sha[:])
|
return base64.RawURLEncoding.EncodeToString(sha[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func issueNonce(w http.ResponseWriter, r *http.Request) {
|
||||||
|
b := make([]byte, 16)
|
||||||
|
_, _ = rand.Read(b)
|
||||||
|
nonce := base64.RawURLEncoding.EncodeToString(b);
|
||||||
|
nonces[nonce] = time.Now().Unix()
|
||||||
|
|
||||||
|
w.Header().Set("Replay-Nonce", nonce);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func requireNonce(next http.HandlerFunc) http.HandlerFunc {
|
||||||
|
return func (w http.ResponseWriter, r *http.Request) {
|
||||||
|
nonce := r.Header.Get("Replay-Nonce")
|
||||||
|
// TODO expire nonces every so often
|
||||||
|
t := nonces[nonce]
|
||||||
|
if 0 == t {
|
||||||
|
http.Error(
|
||||||
|
w,
|
||||||
|
`{ "error": "invalid or expired nonce", "error_code": "ENONCE" }`,
|
||||||
|
http.StatusBadRequest,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(nonces, nonce)
|
||||||
|
issueNonce(w, r)
|
||||||
|
|
||||||
|
next(w, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBaseURL(r *http.Request) string {
|
||||||
|
var scheme string
|
||||||
|
if nil != r.TLS || "https" == r.Header.Get("X-Forwarded-Proto") {
|
||||||
|
scheme = "https:"
|
||||||
|
} else {
|
||||||
|
scheme = "http:"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"%s//%s",
|
||||||
|
scheme,
|
||||||
|
r.Host,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue