verify exp
This commit is contained in:
parent
ca84b8dbca
commit
05db67c8b7
|
@ -7,11 +7,12 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.coolaj86.com/coolaj86/go-mockid/xkeypairs"
|
||||
)
|
||||
|
||||
// VerifyJWT will verify both JWT and uncompressed JWS
|
||||
// Verify will verify both JWT and uncompressed JWS
|
||||
func Verify(w http.ResponseWriter, r *http.Request) {
|
||||
if "POST" != r.Method {
|
||||
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
|
||||
|
@ -55,7 +56,7 @@ func Verify(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
if err := json.Unmarshal([]byte(protected), &jws.Header); nil != err {
|
||||
log.Printf("json decode error: %s", err)
|
||||
log.Printf("json decode header error: %s", err)
|
||||
http.Error(w, "Bad Request: invalid JWS header", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
@ -66,11 +67,16 @@ func Verify(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
if err := json.Unmarshal([]byte(payload), &jws.Claims); nil != err {
|
||||
log.Printf("json decode error: %s", err)
|
||||
log.Printf("json decode claims error: %s", err)
|
||||
http.Error(w, "Bad Request: invalid JWS claims", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if "false" == r.URL.Query().Get("exp") {
|
||||
//expf64, _ := jws.Claims["exp"].(float64)
|
||||
jws.Claims["exp"] = float64(time.Now().Add(5 * time.Minute).Unix())
|
||||
}
|
||||
|
||||
ok, err := xkeypairs.VerifyClaims(nil, jws)
|
||||
if nil != err {
|
||||
log.Printf("jws verify error: %s", err)
|
||||
|
|
|
@ -64,11 +64,39 @@ func TestMain(m *testing.M) {
|
|||
//func TestSelfSignWithoutExp(t *testing.T)
|
||||
//func TestSelfSignWithJTIWithoutExp(t *testing.T)
|
||||
|
||||
func TestVerifySelfSignedJWT(t *testing.T) {
|
||||
func TestVerifyExpired(t *testing.T) {
|
||||
jwt := "eyJfc2VlZCI6LTEzMDY3NDU1MDQxNDQsImFsZyI6IlJTMjU2IiwiandrIjp7ImUiOiJBUUFCIiwia2lkIjoiSEZ4ZTlGV1dVc2N3bjltaVozSXNJeWMwMjMtbEJ1UmtvOEJpVV9IRG9KOCIsImt0eSI6IlJTQSIsIm4iOiJ2NUZkSTdYaC0wekxWVEVQZl94ekdIUVpDcEZ2MWR2N2h3eHhrVjctYmxpYmt6LXIxUG9lZ3lQYzFXMjZlWFBvd0xQQXQ3a3dHQnVOdjdMVjh5MEtvMkxOZklaXzRILW54SkJPaWIybXlHOVVfQ29WRDBiM3NBWTdmcDd2QlV1bTBXYVM4R3hZOGtYU0ZOS0VTY0NDNVBpSmFyblNISk1PcUdIVm51YmpsSjl5c1NyNmNsaGpxc0R4dU9qOHpxamF2MUFxek1STWVpRl9CREJsOUFoUGNZSHpHN0JtaXB5UEo2XzBwdWNLTi0tUDZDRk92d05SVGx2ek41RmlRM3VHcy1fMHcwQzVMZWJ6N21BNmJNTFdXc0tRRFBvb3cxallCWHJKdVF1WkZoSmxLMmdidm9ZcV85dWhfLUM1Z3pPZnR4UHBCNnhtY3RfelVaeUdwUUxnQlEiLCJ1c2UiOiJzaWcifSwidHlwIjoiSldUIn0.eyJleHAiOjE1OTY2MTQ3NTYsInN1YiI6ImJhbmFuYXMifQ.qHpzlglOfZMzE3CTNAUXld_wC62JTAJuoQfMaNeFa-XPtYB2Maj8_w3YmRZg_q5S6y9ToCmZ8nWd1kuMheA5qBKOUQeQH47Jts5zWLd0UBckIHo5lK4mk0bUWuiNgr7c9DY6k1DIdFaavyWCXbhFwG0X83qlMhQlPh02dDpCuU78Nn2hF3mZETQKpBIVESYtfeU1Xy3OU_am0kwcN2klLcdweOcrLx_ONfcvAGY3KiIdFiz0ViySAsQ39BiSSvoDYqOOOi41Hky67bnyZQOdalQC_95McTeXApzmGXRUE74Gj-S8c9e5it5d4QZLPaQ1JHzUKz1s7TPvThIn58NA-g"
|
||||
client := srv.Client()
|
||||
urlstr, _ := url.Parse(srv.URL + "/verify")
|
||||
|
||||
req := &http.Request{
|
||||
Method: "POST",
|
||||
URL: urlstr,
|
||||
Header: http.Header{},
|
||||
}
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", jwt))
|
||||
res, err := client.Do(req)
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
data, err := ioutil.ReadAll(res.Body)
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if 200 == res.StatusCode {
|
||||
log.Printf(string(data))
|
||||
t.Error(fmt.Errorf("did not expect successful status code: %d", res.StatusCode))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifySelfSignedJWT(t *testing.T) {
|
||||
jwt := "eyJfc2VlZCI6LTEzMDY3NDU1MDQxNDQsImFsZyI6IlJTMjU2IiwiandrIjp7ImUiOiJBUUFCIiwia2lkIjoiSEZ4ZTlGV1dVc2N3bjltaVozSXNJeWMwMjMtbEJ1UmtvOEJpVV9IRG9KOCIsImt0eSI6IlJTQSIsIm4iOiJ2NUZkSTdYaC0wekxWVEVQZl94ekdIUVpDcEZ2MWR2N2h3eHhrVjctYmxpYmt6LXIxUG9lZ3lQYzFXMjZlWFBvd0xQQXQ3a3dHQnVOdjdMVjh5MEtvMkxOZklaXzRILW54SkJPaWIybXlHOVVfQ29WRDBiM3NBWTdmcDd2QlV1bTBXYVM4R3hZOGtYU0ZOS0VTY0NDNVBpSmFyblNISk1PcUdIVm51YmpsSjl5c1NyNmNsaGpxc0R4dU9qOHpxamF2MUFxek1STWVpRl9CREJsOUFoUGNZSHpHN0JtaXB5UEo2XzBwdWNLTi0tUDZDRk92d05SVGx2ek41RmlRM3VHcy1fMHcwQzVMZWJ6N21BNmJNTFdXc0tRRFBvb3cxallCWHJKdVF1WkZoSmxLMmdidm9ZcV85dWhfLUM1Z3pPZnR4UHBCNnhtY3RfelVaeUdwUUxnQlEiLCJ1c2UiOiJzaWcifSwidHlwIjoiSldUIn0.eyJleHAiOjE1OTY2MTQ3NTYsInN1YiI6ImJhbmFuYXMifQ.qHpzlglOfZMzE3CTNAUXld_wC62JTAJuoQfMaNeFa-XPtYB2Maj8_w3YmRZg_q5S6y9ToCmZ8nWd1kuMheA5qBKOUQeQH47Jts5zWLd0UBckIHo5lK4mk0bUWuiNgr7c9DY6k1DIdFaavyWCXbhFwG0X83qlMhQlPh02dDpCuU78Nn2hF3mZETQKpBIVESYtfeU1Xy3OU_am0kwcN2klLcdweOcrLx_ONfcvAGY3KiIdFiz0ViySAsQ39BiSSvoDYqOOOi41Hky67bnyZQOdalQC_95McTeXApzmGXRUE74Gj-S8c9e5it5d4QZLPaQ1JHzUKz1s7TPvThIn58NA-g"
|
||||
client := srv.Client()
|
||||
urlstr, _ := url.Parse(srv.URL + "/verify?exp=false")
|
||||
|
||||
req := &http.Request{
|
||||
Method: "POST",
|
||||
URL: urlstr,
|
||||
|
|
|
@ -13,20 +13,27 @@ import (
|
|||
"log"
|
||||
"math/big"
|
||||
mathrand "math/rand"
|
||||
"time"
|
||||
|
||||
"git.rootprojects.org/root/keypairs"
|
||||
)
|
||||
|
||||
func VerifyClaims(pubkey keypairs.PublicKey, jws *JWS) (bool, error) {
|
||||
seed, _ := jws.Header["_seed"].(int64)
|
||||
seedf64, _ := jws.Header["_seed"].(float64)
|
||||
kty, _ := jws.Header["_kty"].(string)
|
||||
kid, _ := jws.Header["kid"].(string)
|
||||
jwkmap, hasJWK := jws.Header["jwk"].(Object)
|
||||
//var jwk JWK = nil
|
||||
|
||||
if 0 == seed {
|
||||
seed = int64(seedf64)
|
||||
}
|
||||
|
||||
var pub keypairs.PublicKey = nil
|
||||
if hasJWK {
|
||||
fmt.Println("Security TODO: did not check jws.Claims[\"sub\"] against 'jwk' thumbprint")
|
||||
fmt.Println("Security TODO: did not check jws.Claims[\"iss\"]")
|
||||
log.Println("Security TODO: did not check jws.Claims[\"sub\"] against 'jwk' thumbprint")
|
||||
log.Println("Security TODO: did not check jws.Claims[\"iss\"]")
|
||||
kty := jwkmap["kty"]
|
||||
var err error
|
||||
if "RSA" == kty {
|
||||
|
@ -70,7 +77,20 @@ func VerifyClaims(pubkey keypairs.PublicKey, jws *JWS) (bool, error) {
|
|||
} else {
|
||||
pub = pubkey
|
||||
}
|
||||
fmt.Println("Security TODO: did not check jws.Claims[\"kid\"] against thumbprint")
|
||||
log.Println("Security TODO: did not check jws.Claims[\"kid\"] against thumbprint")
|
||||
}
|
||||
|
||||
jti, _ := jws.Claims["jti"].(string)
|
||||
expf64, _ := jws.Claims["exp"].(float64)
|
||||
exp := int64(expf64)
|
||||
if 0 == exp {
|
||||
if "" == jti {
|
||||
return false, errors.New("one of 'jti' or 'exp' must exist for token expiry")
|
||||
}
|
||||
} else {
|
||||
if time.Now().Unix() > exp {
|
||||
return false, fmt.Errorf("token expired at %d (%s)", exp, time.Unix(exp, 0))
|
||||
}
|
||||
}
|
||||
|
||||
signable := fmt.Sprintf("%s.%s", jws.Protected, jws.Payload)
|
||||
|
@ -103,8 +123,6 @@ func Verify(pubkey keypairs.PublicKey, hash []byte, sig []byte) bool {
|
|||
r.SetBytes(sig[0:32])
|
||||
s := &big.Int{}
|
||||
s.SetBytes(sig[32:])
|
||||
fmt.Println("debug: sig len:", len(sig))
|
||||
fmt.Println("debug: r, s:", r, s)
|
||||
return ecdsa.Verify(pub, hash, r, s)
|
||||
default:
|
||||
panic("impossible condition: non-rsa/non-ecdsa key")
|
||||
|
@ -134,6 +152,7 @@ func genPrivKey(seed int64, kty string) keypairs.PrivateKey {
|
|||
}
|
||||
if maxRetry == i-1 {
|
||||
log.Printf("error: coinflip landed on heads %d times", maxRetry)
|
||||
// TODO return random / retry error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue