func TestDecodeClaims(t *testing.T) { s := []byte(`{"iss":"issuer","sub":"subject","aud":["a1","a2"],"exp":1451610000,"iat":1451606400}`) now := time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC) c := Claims{} if err := json.Unmarshal(s, &c); assert.NoError(t, err) { assert.Equal(t, "issuer", c.Issuer) assert.Equal(t, "subject", c.Subject) assert.Equal(t, Audience{"a1", "a2"}, c.Audience) assert.True(t, now.Equal(c.IssuedAt.Time())) assert.True(t, now.Add(1*time.Hour).Equal(c.Expiry.Time())) } s2 := []byte(`{"aud": "a1"}`) c2 := Claims{} if err := json.Unmarshal(s2, &c2); assert.NoError(t, err) { assert.Equal(t, Audience{"a1"}, c2.Audience) } invalid := []struct { Raw string Err error }{ {`{"aud": 5}`, ErrUnmarshalAudience}, {`{"aud": ["foo", 5, "bar"]}`, ErrUnmarshalAudience}, {`{"exp": "invalid"}`, ErrUnmarshalNumericDate}, } for _, v := range invalid { c := Claims{} assert.Equal(t, v.Err, json.Unmarshal([]byte(v.Raw), &c)) } }
func TestJWKSymmetricKey(t *testing.T) { sample1 := `{"kty":"oct","alg":"A128KW","k":"GawgguFyGrWKav7AX4VKUg"}` sample2 := `{"kty":"oct","k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow","kid":"HMAC key used in JWS spec Appendix A.1 example"}` var jwk1 JSONWebKey json.Unmarshal([]byte(sample1), &jwk1) if jwk1.Algorithm != "A128KW" { t.Errorf("expected Algorithm to be A128KW, but was '%s'", jwk1.Algorithm) } expected1 := fromHexBytes("19ac2082e1721ab58a6afec05f854a52") if !bytes.Equal(jwk1.Key.([]byte), expected1) { t.Errorf("expected Key to be '%s', but was '%s'", hex.EncodeToString(expected1), hex.EncodeToString(jwk1.Key.([]byte))) } var jwk2 JSONWebKey json.Unmarshal([]byte(sample2), &jwk2) if jwk2.KeyID != "HMAC key used in JWS spec Appendix A.1 example" { t.Errorf("expected KeyID to be 'HMAC key used in JWS spec Appendix A.1 example', but was '%s'", jwk2.KeyID) } expected2 := fromHexBytes(` 0323354b2b0fa5bc837e0665777ba68f5ab328e6f054c928a90f84b2d2502ebf d3fb5a92d20647ef968ab4c377623d223d2e2172052e4f08c0cd9af567d080a3`) if !bytes.Equal(jwk2.Key.([]byte), expected2) { t.Errorf("expected Key to be '%s', but was '%s'", hex.EncodeToString(expected2), hex.EncodeToString(jwk2.Key.([]byte))) } }
func TestMarshalNonPointer(t *testing.T) { type EmbedsKey struct { Key JSONWebKey } keyJSON := []byte(`{ "e": "AQAB", "kty": "RSA", "n": "vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw" }`) var parsedKey JSONWebKey err := json.Unmarshal(keyJSON, &parsedKey) if err != nil { t.Errorf("Error unmarshalling key: %v", err) return } ek := EmbedsKey{ Key: parsedKey, } out, err := json.Marshal(ek) if err != nil { t.Errorf("Error marshalling JSON: %v", err) return } expected := "{\"Key\":{\"kty\":\"RSA\",\"n\":\"vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw\",\"e\":\"AQAB\"}}" if string(out) != expected { t.Error("Failed to marshal embedded non-pointer JWK properly:", string(out)) } }
// parseSignedFull parses a message in full format. func parseSignedFull(input string) (*JSONWebSignature, error) { var parsed rawJSONWebSignature err := json.Unmarshal([]byte(input), &parsed) if err != nil { return nil, err } return parsed.sanitized() }
func normalize(i interface{}) (map[string]interface{}, error) { m := make(map[string]interface{}) raw, err := json.Marshal(i) if err != nil { return nil, err } if err := json.Unmarshal(raw, &m); err != nil { return nil, err } return m, nil }
// Claims deserializes a JSONWebToken into dest using the provided key. func (t *JSONWebToken) Claims(key interface{}, dest ...interface{}) error { b, err := t.payload(key) if err != nil { return err } for _, d := range dest { if err := json.Unmarshal(b, d); err != nil { return err } } return nil }
func TestSignerKid(t *testing.T) { kid := "DEADBEEF" payload := []byte("Lorem ipsum dolor sit amet") key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Error("problem generating test signing key", err) } basejwk := JSONWebKey{Key: key} jsonbar, err := basejwk.MarshalJSON() if err != nil { t.Error("problem marshalling base JWK", err) } var jsonmsi map[string]interface{} err = json.Unmarshal(jsonbar, &jsonmsi) if err != nil { t.Error("problem unmarshalling base JWK", err) } jsonmsi["kid"] = kid jsonbar2, err := json.Marshal(jsonmsi) if err != nil { t.Error("problem marshalling kided JWK", err) } var jwk JSONWebKey err = jwk.UnmarshalJSON(jsonbar2) if err != nil { t.Error("problem unmarshalling kided JWK", err) } signer, err := NewSigner(SigningKey{ES256, &jwk}, nil) if err != nil { t.Error("problem creating signer", err) } signed, err := signer.Sign(payload) serialized := signed.FullSerialize() parsed, err := ParseSigned(serialized) if err != nil { t.Error("problem parsing signed object", err) } if parsed.Signatures[0].Header.KeyID != kid { t.Error("KeyID did not survive trip") } }
// UnmarshalJSON reads a key from its JSON representation. func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { var raw rawJSONWebKey err = json.Unmarshal(data, &raw) if err != nil { return err } var key interface{} switch raw.Kty { case "EC": if raw.D != nil { key, err = raw.ecPrivateKey() } else { key, err = raw.ecPublicKey() } case "RSA": if raw.D != nil { key, err = raw.rsaPrivateKey() } else { key, err = raw.rsaPublicKey() } case "oct": key, err = raw.symmetricKey() default: err = fmt.Errorf("square/go-jose: unknown json web key type '%s'", raw.Kty) } if err == nil { *k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use} } k.Certificates = make([]*x509.Certificate, len(raw.X5c)) for i, cert := range raw.X5c { raw, err := base64.StdEncoding.DecodeString(cert) if err != nil { return err } k.Certificates[i], err = x509.ParseCertificate(raw) if err != nil { return err } } return }
func TestMarshalUnmarshalJWKSet(t *testing.T) { jwk1 := JSONWebKey{Key: rsaTestKey, KeyID: "ABCDEFG", Algorithm: "foo"} jwk2 := JSONWebKey{Key: rsaTestKey, KeyID: "GFEDCBA", Algorithm: "foo"} var set JSONWebKeySet set.Keys = append(set.Keys, jwk1) set.Keys = append(set.Keys, jwk2) jsonbar, err := json.Marshal(&set) if err != nil { t.Error("problem marshalling set", err) } var set2 JSONWebKeySet err = json.Unmarshal(jsonbar, &set2) if err != nil { t.Error("problem unmarshalling set", err) } jsonbar2, err := json.Marshal(&set2) if err != nil { t.Error("problem marshalling set", err) } if !bytes.Equal(jsonbar, jsonbar2) { t.Error("roundtrip should not lose information") } }
// sanitized produces a cleaned-up JWS object from the raw JSON. func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) { if parsed.Payload == nil { return nil, fmt.Errorf("square/go-jose: missing payload in JWS message") } obj := &JSONWebSignature{ payload: parsed.Payload.bytes(), Signatures: make([]Signature, len(parsed.Signatures)), } if len(parsed.Signatures) == 0 { // No signatures array, must be flattened serialization signature := Signature{} if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 { signature.protected = &rawHeader{} err := json.Unmarshal(parsed.Protected.bytes(), signature.protected) if err != nil { return nil, err } } // Check that there is not a nonce in the unprotected header if parsed.Header != nil && parsed.Header.Nonce != "" { return nil, ErrUnprotectedNonce } signature.header = parsed.Header signature.Signature = parsed.Signature.bytes() // Make a fake "original" rawSignatureInfo to store the unprocessed // Protected header. This is necessary because the Protected header can // contain arbitrary fields not registered as part of the spec. See // https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-4 // If we unmarshal Protected into a rawHeader with its explicit list of fields, // we cannot marshal losslessly. So we have to keep around the original bytes. // This is used in computeAuthData, which will first attempt to use // the original bytes of a protected header, and fall back on marshaling the // header struct only if those bytes are not available. signature.original = &rawSignatureInfo{ Protected: parsed.Protected, Header: parsed.Header, Signature: parsed.Signature, } signature.Header = signature.mergedHeaders().sanitized() // As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded. jwk := signature.Header.JSONWebKey if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) { return nil, errors.New("square/go-jose: invalid embedded jwk, must be public key") } obj.Signatures = append(obj.Signatures, signature) } for i, sig := range parsed.Signatures { if sig.Protected != nil && len(sig.Protected.bytes()) > 0 { obj.Signatures[i].protected = &rawHeader{} err := json.Unmarshal(sig.Protected.bytes(), obj.Signatures[i].protected) if err != nil { return nil, err } } // Check that there is not a nonce in the unprotected header if sig.Header != nil && sig.Header.Nonce != "" { return nil, ErrUnprotectedNonce } obj.Signatures[i].Header = obj.Signatures[i].mergedHeaders().sanitized() obj.Signatures[i].Signature = sig.Signature.bytes() // As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded. jwk := obj.Signatures[i].Header.JSONWebKey if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) { return nil, errors.New("square/go-jose: invalid embedded jwk, must be public key") } // Copy value of sig original := sig obj.Signatures[i].header = sig.Header obj.Signatures[i].original = &original } return obj, nil }
func UnmarshalJSON(data []byte, v interface{}) error { return json.Unmarshal(data, v) }