github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/pkg/usertokens/pkitokens/jwt_test.go (about) 1 // +build !windows 2 3 package pkitokens 4 5 import ( 6 "context" 7 "crypto" 8 "testing" 9 10 . "github.com/smartystreets/goconvey/convey" 11 ) 12 13 func TestPKIVerifierValidate(t *testing.T) { 14 15 ctx := context.TODO() 16 pemBytes := []byte(` 17 -----BEGIN PUBLIC KEY----- 18 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyjDEPJD1Fv1IJIq4mnec 19 oMlSve0vZOTuzDmKuMB4vfBXalKZgbp4ONL+BvWV9OPs22Smv9SAfnoQ25q8Q9so 20 ihzUKhaIAY2CI70ll4exbLK9FD4uTi1bqn0FdIh04UIyW6s2EqTGMkSKx9THNvAM 21 Kx++pPt3US2sQVEC24bWPxRN7RsBBpRjoiEamkA04ioGFhMBbas5MdCLt/fd92aR 22 QCBISOb6PU08fQiARK8g/wdpBUTxy9/Ud1vUnNaZtWm+eLrwdTXgHM3/LG1M4lc0 23 ZqHIL3rMxhae5W+j3SL3ApreiUYugv/0bCSypvJZjEXKS7SBR/+rtw0/mQpS8DpI 24 kwIDAQAB 25 -----END PUBLIC KEY----- 26 -----BEGIN PUBLIC KEY----- 27 MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnlK01BDTYbvRBxGM0o3vXNqqvI25 28 eZ/s3Cq9OXnNpoCI3/DH/tuD3n7cnWcNSfl1qJIH2LVZ0cWUW/L/9i/jPA== 29 -----END PUBLIC KEY----- 30 `) 31 32 // Here are the private keys in case you want to regenerate a new token: 33 // 34 // -----BEGIN RSA PRIVATE KEY----- 35 // MIIEpAIBAAKCAQEAyjDEPJD1Fv1IJIq4mnecoMlSve0vZOTuzDmKuMB4vfBXalKZ 36 // gbp4ONL+BvWV9OPs22Smv9SAfnoQ25q8Q9soihzUKhaIAY2CI70ll4exbLK9FD4u 37 // Ti1bqn0FdIh04UIyW6s2EqTGMkSKx9THNvAMKx++pPt3US2sQVEC24bWPxRN7RsB 38 // BpRjoiEamkA04ioGFhMBbas5MdCLt/fd92aRQCBISOb6PU08fQiARK8g/wdpBUTx 39 // y9/Ud1vUnNaZtWm+eLrwdTXgHM3/LG1M4lc0ZqHIL3rMxhae5W+j3SL3ApreiUYu 40 // gv/0bCSypvJZjEXKS7SBR/+rtw0/mQpS8DpIkwIDAQABAoIBAQCWkraxfCpp0nn1 41 // bLGJp2Ynf4Z1Frvi4XLM+FVMvVmt6dzPu2/CYsHBX6/6Ms5YL51mzZA47+I5TmJb 42 // iOKHjiCkqk9+gIUM0vuF7giezljdYEbbWmtVoQXQ84YqgKy6THgAOILuY3OOX+kS 43 // ZG1vhlkpjFyHtRXoiKDti40bO1E2a2+O/vpD417hZrezzb97JQ4Cw417jRs3+dpc 44 // BaVutFUiIm5HFeVdD0/hqwnYMPeoxxxdj4kiuzI2FZOexPufq9MSrSI0RMnegRGL 45 // 8fgg4ZhVuEONtA8eXFI8EpIEhaKOq9CPZuImyKh+Vx4pwcT7NVld70ohqhQaEVqs 46 // 6QblHf6hAoGBAOqimWdjGY6PKT6ipF9/6CsNnAAyyG1IRWSLweVDK36DkIxzTKGU 47 // fk2uXFw6GlAKu1J0lTfQjxtKoYVljUHjUvfvW9KE/GyuW6eWTxUIrvmpvpcyAV6H 48 // gHkt8/A+l8sQS3oMiLJ14c8/W5d4YdB/VBLQHsOi8I5EOGsO7a52fETLAoGBANyZ 49 // 3+nq/tyk6hGk+lNJSXnkURydbkONCFhU92iwPC+f/4ILcHdBVjwLOAYa/qUzHvEE 50 // H+MtMiuGbDrnjjCytvjmIKmMnJ30BHbXwn0dV+hes1O0EwHoIGtvQyWVH/6zB4ar 51 // YkhK9IBtOxfs3ORVeVBoHx/Mq40BAGzGxQQopVpZAoGAScFtCWPMb9SuuWK02tRB 52 // Le9sP1+3Qyr5rT6FZ8TykiVXNd80koI0JcUOgWs+RDTrZ2MAWPg1U/XkyiL/AVwt 53 // A4T5TzbAhoVUiFymZU1Ce3aRU8PDTGy5xN3eFYIHgyyPHUF9YuPNZLFc4ENWNA0i 54 // Z3uGgCbjCUWGmpipvDLAo3sCgYApQEDlvgLAgbofaIlCz76Eo5QjVLEMwq+fzOui 55 // 0OnAQhwGVltGgZo9ih+EzMF3ZNLRYOMRmR77kpxke25UXubmLipHajrTMpEvI/OD 56 // b9xDYIoKCe9P+Pcu/9Q/j942w4WRwjSTriiAZ2yYcbtwmycfSQkg6iXeLSTGMnke 57 // 6PbaqQKBgQDGNwOgdHtMdHyy2kDMLdGKCysEo2eBNAxdRqjGxmsjm6bsd4xyLxS2 58 // lkf7v3e9vE24HfBbwMoW4sx1eEDbFc4pai4l4vG3dpbrd3CJa5mpvL3mxGnTlPUy 59 // 1PopL5pyjSZ6bcRETolZNM4L8X4jgfwHl3Lvc5jBgQW0PCAVtBVp8g== 60 // -----END RSA PRIVATE KEY----- 61 // 62 // -----BEGIN EC PRIVATE KEY----- 63 // MHcCAQEEIBP/5KHpYJ1GwqdOUOCu4+264KP4loONT+9QIzNJwVGjoAoGCCqGSM49 64 // AwEHoUQDQgAEnlK01BDTYbvRBxGM0o3vXNqqvI25eZ/s3Cq9OXnNpoCI3/DH/tuD 65 // 3n7cnWcNSfl1qJIH2LVZ0cWUW/L/9i/jPA== 66 // -----END EC PRIVATE KEY----- 67 // 68 // And here is the payload data: 69 // 70 // { 71 // "sub": "Adam", 72 // "name": "Eve", 73 // "admin": true, 74 // "iat": 1516239022 75 // } 76 // 77 // Go to https://jwt.io/ and 78 // - select the right algorithm (RS256 / ES256) 79 // - fill in the public key 80 // - fill in the private key 81 // - ensure the token is still valid (shows Signature Verified) 82 // - copy the new token from the encoded section 83 // 84 validTokenRS256 := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJBZGFtIiwibmFtZSI6IkV2ZSIsImFkbWluIjp0cnVlLCJpYXQiOjE1MTYyMzkwMjJ9.WHDAmZzmX50GRSXTvB0MqQl2gFHFrQav-v6V2MdbqGXvmBZXus9Bl965Uuqs8uxdJzDad8Is05kC77iHElTasgQZqLwSTN5-WXpZFsW_EOGVcy0puDgREm2QcD8pQeagy6KxwDs0BAQIWwPSfjTCn05w-CRKveo1t0TsKUSMiZltebaZOtAr9etOAwBHIy7QzexrhIzlG6-7fqMbpsNZ8DbanUBc2fiL6Ogs461TQixBDHoRw2HjykGoPRvH3sy8bSRX5l1olBkRb4kic7xSKhiU_YlvmBo9ybC81TRGUtQZl87aLcnv4foDLtFvNAwTyTxfikt2Ka1peKJNgk82Dw" 85 validTokenES256 := "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJBZGFtIiwibmFtZSI6IkV2ZSIsImFkbWluIjp0cnVlLCJpYXQiOjE1MTYyMzkwMjJ9.V9HGK6yEZBbjgEsyhQeU6i0Io1KZaCMVgSC0u6fQTRd2TX4Ac-FSDnf44s89PPm8RCHqBATJdJMspIQM66y9Hw" 86 87 // currently unsupported algorithm PS256 88 unsupportedTokenPS256 := "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.P9_X1ctIxnnoUpKSWpYw3rF62e-d8LXe3sETuLn4Lhigw5OQhi-mBBKoBMneHy4kimS84zxnMby0FYo9wKM3I3pEg8Qrz0Q00tNhKCwOnZ7Q-e86sW1luK1z82tufF-sZ9_BY_LGQsym0lQmQaHFzLmEDXnOzWsjUThHGVJTI64" 89 90 // supported algorithm but signed with a different key 91 invalidTokenRS256 := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.TCYt5XsITJX1CxPCT8yAV-TVkIEq_PbChOMqsLfRoPsnsgw5WEuts01mq-pQy7UJiN5mgRxD-WUcX16dUEMGlv50aqzpqh4Qktb3rk-BuQy72IFLOqV0G_zS245-kronKb78cPN25DGlcTwLtjPAYuNzVBAh4vGHSrQyHUdBBPM" 92 93 Convey("Given a valid PEM", t, func() { 94 95 Convey("it should create a new verifier successfully using NewVerifier()", func() { 96 verifier, err := NewVerifier(&PKIJWTVerifier{ 97 JWTCertPEM: pemBytes, 98 }) 99 So(err, ShouldBeNil) 100 So(verifier, ShouldNotBeNil) 101 So(len(verifier.keys), ShouldEqual, 2) 102 }) 103 104 Convey("it should create a new verifier successfully using NewVerifierFromPEM()", func() { 105 verifier, err := NewVerifierFromPEM(pemBytes, "", false, false) 106 So(err, ShouldBeNil) 107 So(verifier, ShouldNotBeNil) 108 So(len(verifier.keys), ShouldEqual, 2) 109 }) 110 }) 111 112 Convey("Given a verifier with no loaded public keys", t, func() { 113 verifier := &PKIJWTVerifier{ 114 JWTCertPEM: pemBytes, 115 keys: []crypto.PublicKey{}, 116 } 117 118 Convey("it should fail to validate", func() { 119 token := "not empty token" 120 _, _, _, err := verifier.Validate(ctx, token) 121 So(err, ShouldNotBeNil) 122 So(err.Error(), ShouldEqual, "No public keys loaded into verifier") 123 }) 124 }) 125 126 Convey("Given a valid verifier", t, func() { 127 verifier, err := NewVerifierFromPEM(pemBytes, "", false, false) 128 So(verifier, ShouldNotBeNil) 129 So(err, ShouldBeNil) 130 So(len(verifier.keys), ShouldEqual, 2) 131 132 Convey("it should fail to validate an empty token", func() { 133 token := "" 134 _, _, _, err := verifier.Validate(ctx, token) 135 So(err, ShouldNotBeNil) 136 So(err.Error(), ShouldEqual, "Empty token") 137 }) 138 139 Convey("it should validate a valid RS256 token successfully", func() { 140 token := validTokenRS256 141 attributes, _, _, err := verifier.Validate(ctx, token) 142 So(err, ShouldBeNil) 143 So(len(attributes), ShouldBeGreaterThan, 0) 144 So(attributes, ShouldContain, "sub=Adam") 145 So(attributes, ShouldContain, "name=Eve") 146 }) 147 148 Convey("it should validate a valid ES256 token successfully", func() { 149 token := validTokenES256 150 attributes, _, _, err := verifier.Validate(ctx, token) 151 So(err, ShouldBeNil) 152 So(len(attributes), ShouldBeGreaterThan, 0) 153 So(attributes, ShouldContain, "sub=Adam") 154 So(attributes, ShouldContain, "name=Eve") 155 }) 156 157 Convey("it should fail to validate a token signed with an unsupported algorithm", func() { 158 token := unsupportedTokenPS256 159 _, _, _, err := verifier.Validate(ctx, token) 160 So(err, ShouldNotBeNil) 161 So(err.Error(), ShouldEqual, "Invalid token - errors: [unsupported signing method '*jwt.SigningMethodRSAPSS'; unsupported signing method '*jwt.SigningMethodRSAPSS']") 162 }) 163 164 Convey("it should fail to validate a token signed with an unexpected key", func() { 165 token := invalidTokenRS256 166 _, _, _, err := verifier.Validate(ctx, token) 167 So(err, ShouldNotBeNil) 168 So(err.Error(), ShouldEqual, "Invalid token - errors: [crypto/rsa: verification error; signing method '*jwt.SigningMethodRSA' and public key type '*ecdsa.PublicKey' mismatch]") 169 }) 170 }) 171 }