diff --git a/jwt/jwt.go b/jwt/jwt.go index 0870fa8..5c34f76 100644 --- a/jwt/jwt.go +++ b/jwt/jwt.go @@ -22,7 +22,7 @@ func Decode(jwt string) (Decoded, error) { header, err := jws.DecodeHeader(parts[0]) if err != nil { - return Decoded{}, err + return Decoded{}, fmt.Errorf("malformed JWT. Failed to decode header: %w", err) } claimsBytes, err := base64.RawURLEncoding.DecodeString(parts[1]) @@ -41,11 +41,17 @@ func Decode(jwt string) (Decoded, error) { return Decoded{}, fmt.Errorf("malformed JWT. Failed to decode signature: %w", err) } + signerDid, err := did.Parse(header.KID) + if err != nil { + return Decoded{}, fmt.Errorf("malformed JWT. Failed to parse signer DID: %w", err) + } + return Decoded{ Header: header, Claims: claims, Signature: signature, Parts: parts, + SignerDID: signerDid, }, nil } @@ -134,6 +140,7 @@ type Decoded struct { Claims Claims Signature []byte Parts []string + SignerDID did.DID } // Verify verifies a JWT (JSON Web Token) diff --git a/jwt/jwt_test.go b/jwt/jwt_test.go index 554513d..da8cbf8 100644 --- a/jwt/jwt_test.go +++ b/jwt/jwt_test.go @@ -114,3 +114,30 @@ func Test_Decode_Empty(t *testing.T) { assert.Error(t, err) assert.Equal(t, jwt.Decoded{}, decoded) } + +func Test_Decode_Works(t *testing.T) { + vcJwt := `eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDpqd2s6ZXlKcmRIa2lPaUpQUzFBaUxDSmpjbllpT2lKRlpESTFOVEU1SWl3aWVDSTZJbkY0VjFGS2F6RTJSbWhCZWtOQlRsRktaR1F5UTFkRldrcE9lbXBSYjNGSmRYWk5SbUpVWjFKTVNFRWlmUSMwIiwidHlwIjoiSldUIn0.eyJleHAiOjE3MjQ1MzQwNTAsImlzcyI6ImRpZDpqd2s6ZXlKcmRIa2lPaUpQUzFBaUxDSmpjbllpT2lKRlpESTFOVEU1SWl3aWVDSTZJbkY0VjFGS2F6RTJSbWhCZWtOQlRsRktaR1F5UTFkRldrcE9lbXBSYjNGSmRYWk5SbUpVWjFKTVNFRWlmUSIsImp0aSI6InVybjp2Yzp1dWlkOjlkMzdmMzY3LWE4ZDctNDY4Zi05NGYwLTk1NzAxNzBkNzZhNCIsIm5iZiI6MTcyMTk0MjA1MCwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6andrOmV5SnJkSGtpT2lKUFMxQWlMQ0pqY25ZaU9pSkZaREkxTlRFNUlpd2llQ0k2SW5GNFYxRkthekUyUm1oQmVrTkJUbEZLWkdReVExZEZXa3BPZW1wUmIzRkpkWFpOUm1KVVoxSk1TRUVpZlEiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpc3N1ZXIiOiJkaWQ6andrOmV5SnJkSGtpT2lKUFMxQWlMQ0pqY25ZaU9pSkZaREkxTlRFNUlpd2llQ0k2SW5GNFYxRkthekUyUm1oQmVrTkJUbEZLWkdReVExZEZXa3BPZW1wUmIzRkpkWFpOUm1KVVoxSk1TRUVpZlEifSwiaWQiOiJ1cm46dmM6dXVpZDo5ZDM3ZjM2Ny1hOGQ3LTQ2OGYtOTRmMC05NTcwMTcwZDc2YTQiLCJpc3N1YW5jZURhdGUiOiIyMDI0LTA3LTI1VDIxOjE0OjEwWiIsImV4cGlyYXRpb25EYXRlIjoiMjAyNC0wOC0yNFQyMToxNDoxMFoiLCJjcmVkZW50aWFsU2NoZW1hIjpbeyJ0eXBlIjoiSnNvblNjaGVtYSIsImlkIjoiaHR0cHM6Ly92Yy5zY2hlbWFzLmhvc3Qva2JjLnNjaGVtYS5qc29uIn1dfX0.VwvrU5Lmv3rn9rzXB0OCxe-MtE5R0876pXsXNLRuQjoqSNB5tBv_12NqrobwA-LkMzFwzdQ5-LWJni6grGdXCQ` + decoded, err := jwt.Decode(vcJwt) + assert.NoError(t, err) + assert.Equal(t, decoded.Header.ALG, "EdDSA") + assert.Equal(t, decoded.Header.KID, "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5IiwieCI6InF4V1FKazE2RmhBekNBTlFKZGQyQ1dFWkpOempRb3FJdXZNRmJUZ1JMSEEifQ#0") + assert.NotZero(t, decoded.SignerDID) +} + +func Test_Decode_Bad_Header(t *testing.T) { + vcJwt := `kakaHeader.eyJleHAiOjE3MjQ1MzQwNTAsImlzcyI6ImRpZDpqd2s6ZXlKcmRIa2lPaUpQUzFBaUxDSmpjbllpT2lKRlpESTFOVEU1SWl3aWVDSTZJbkY0VjFGS2F6RTJSbWhCZWtOQlRsRktaR1F5UTFkRldrcE9lbXBSYjNGSmRYWk5SbUpVWjFKTVNFRWlmUSIsImp0aSI6InVybjp2Yzp1dWlkOjlkMzdmMzY3LWE4ZDctNDY4Zi05NGYwLTk1NzAxNzBkNzZhNCIsIm5iZiI6MTcyMTk0MjA1MCwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6andrOmV5SnJkSGtpT2lKUFMxQWlMQ0pqY25ZaU9pSkZaREkxTlRFNUlpd2llQ0k2SW5GNFYxRkthekUyUm1oQmVrTkJUbEZLWkdReVExZEZXa3BPZW1wUmIzRkpkWFpOUm1KVVoxSk1TRUVpZlEiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpc3N1ZXIiOiJkaWQ6andrOmV5SnJkSGtpT2lKUFMxQWlMQ0pqY25ZaU9pSkZaREkxTlRFNUlpd2llQ0k2SW5GNFYxRkthekUyUm1oQmVrTkJUbEZLWkdReVExZEZXa3BPZW1wUmIzRkpkWFpOUm1KVVoxSk1TRUVpZlEifSwiaWQiOiJ1cm46dmM6dXVpZDo5ZDM3ZjM2Ny1hOGQ3LTQ2OGYtOTRmMC05NTcwMTcwZDc2YTQiLCJpc3N1YW5jZURhdGUiOiIyMDI0LTA3LTI1VDIxOjE0OjEwWiIsImV4cGlyYXRpb25EYXRlIjoiMjAyNC0wOC0yNFQyMToxNDoxMFoiLCJjcmVkZW50aWFsU2NoZW1hIjpbeyJ0eXBlIjoiSnNvblNjaGVtYSIsImlkIjoiaHR0cHM6Ly92Yy5zY2hlbWFzLmhvc3Qva2JjLnNjaGVtYS5qc29uIn1dfX0.VwvrU5Lmv3rn9rzXB0OCxe-MtE5R0876pXsXNLRuQjoqSNB5tBv_12NqrobwA-LkMzFwzdQ5-LWJni6grGdXCQ` + _, err := jwt.Decode(vcJwt) + assert.Error(t, err) +} + +func Test_Decode_Bad_Signature(t *testing.T) { + vcJwt := `eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDpqd2s6ZXlKcmRIa2lPaUpQUzFBaUxDSmpjbllpT2lKRlpESTFOVEU1SWl3aWVDSTZJbkY0VjFGS2F6RTJSbWhCZWtOQlRsRktaR1F5UTFkRldrcE9lbXBSYjNGSmRYWk5SbUpVWjFKTVNFRWlmUSMwIiwidHlwIjoiSldUIn0.eyJleHAiOjE3MjQ1MzQwNTAsImlzcyI6ImRpZDpqd2s6ZXlKcmRIa2lPaUpQUzFBaUxDSmpjbllpT2lKRlpESTFOVEU1SWl3aWVDSTZJbkY0VjFGS2F6RTJSbWhCZWtOQlRsRktaR1F5UTFkRldrcE9lbXBSYjNGSmRYWk5SbUpVWjFKTVNFRWlmUSIsImp0aSI6InVybjp2Yzp1dWlkOjlkMzdmMzY3LWE4ZDctNDY4Zi05NGYwLTk1NzAxNzBkNzZhNCIsIm5iZiI6MTcyMTk0MjA1MCwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6andrOmV5SnJkSGtpT2lKUFMxQWlMQ0pqY25ZaU9pSkZaREkxTlRFNUlpd2llQ0k2SW5GNFYxRkthekUyUm1oQmVrTkJUbEZLWkdReVExZEZXa3BPZW1wUmIzRkpkWFpOUm1KVVoxSk1TRUVpZlEiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpc3N1ZXIiOiJkaWQ6andrOmV5SnJkSGtpT2lKUFMxQWlMQ0pqY25ZaU9pSkZaREkxTlRFNUlpd2llQ0k2SW5GNFYxRkthekUyUm1oQmVrTkJUbEZLWkdReVExZEZXa3BPZW1wUmIzRkpkWFpOUm1KVVoxSk1TRUVpZlEifSwiaWQiOiJ1cm46dmM6dXVpZDo5ZDM3ZjM2Ny1hOGQ3LTQ2OGYtOTRmMC05NTcwMTcwZDc2YTQiLCJpc3N1YW5jZURhdGUiOiIyMDI0LTA3LTI1VDIxOjE0OjEwWiIsImV4cGlyYXRpb25EYXRlIjoiMjAyNC0wOC0yNFQyMToxNDoxMFoiLCJjcmVkZW50aWFsU2NoZW1hIjpbeyJ0eXBlIjoiSnNvblNjaGVtYSIsImlkIjoiaHR0cHM6Ly92Yy5zY2hlbWFzLmhvc3Qva2JjLnNjaGVtYS5qc29uIn1dfX0.kakaSignature` + _, err := jwt.Decode(vcJwt) + assert.Error(t, err) +} + +func Test_Decode_HeaderKID_InvalidDID(t *testing.T) { + vcJwt := `eyJhbGciOiJFZERTQSIsImtpZCI6Imtha2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MjQ1MzQwNTAsImlzcyI6ImRpZDpqd2s6ZXlKcmRIa2lPaUpQUzFBaUxDSmpjbllpT2lKRlpESTFOVEU1SWl3aWVDSTZJbkY0VjFGS2F6RTJSbWhCZWtOQlRsRktaR1F5UTFkRldrcE9lbXBSYjNGSmRYWk5SbUpVWjFKTVNFRWlmUSIsImp0aSI6InVybjp2Yzp1dWlkOjlkMzdmMzY3LWE4ZDctNDY4Zi05NGYwLTk1NzAxNzBkNzZhNCIsIm5iZiI6MTcyMTk0MjA1MCwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6andrOmV5SnJkSGtpT2lKUFMxQWlMQ0pqY25ZaU9pSkZaREkxTlRFNUlpd2llQ0k2SW5GNFYxRkthekUyUm1oQmVrTkJUbEZLWkdReVExZEZXa3BPZW1wUmIzRkpkWFpOUm1KVVoxSk1TRUVpZlEiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpc3N1ZXIiOiJkaWQ6andrOmV5SnJkSGtpT2lKUFMxQWlMQ0pqY25ZaU9pSkZaREkxTlRFNUlpd2llQ0k2SW5GNFYxRkthekUyUm1oQmVrTkJUbEZLWkdReVExZEZXa3BPZW1wUmIzRkpkWFpOUm1KVVoxSk1TRUVpZlEifSwiaWQiOiJ1cm46dmM6dXVpZDo5ZDM3ZjM2Ny1hOGQ3LTQ2OGYtOTRmMC05NTcwMTcwZDc2YTQiLCJpc3N1YW5jZURhdGUiOiIyMDI0LTA3LTI1VDIxOjE0OjEwWiIsImV4cGlyYXRpb25EYXRlIjoiMjAyNC0wOC0yNFQyMToxNDoxMFoiLCJjcmVkZW50aWFsU2NoZW1hIjpbeyJ0eXBlIjoiSnNvblNjaGVtYSIsImlkIjoiaHR0cHM6Ly92Yy5zY2hlbWFzLmhvc3Qva2JjLnNjaGVtYS5qc29uIn1dfX0.VwvrU5Lmv3rn9rzXB0OCxe-MtE5R0876pXsXNLRuQjoqSNB5tBv_12NqrobwA-LkMzFwzdQ5-LWJni6grGdXCQ` + _, err := jwt.Decode(vcJwt) + assert.Error(t, err) +} \ No newline at end of file diff --git a/web5-spec b/web5-spec index 4c06416..35f3dcf 160000 --- a/web5-spec +++ b/web5-spec @@ -1 +1 @@ -Subproject commit 4c064165858a89850db9631a3197940ef32c788e +Subproject commit 35f3dcf7bfe321d92eb7d55a039fc139ef22097a