diff --git a/communication/auth/service.go b/communication/auth/service.go index 20d7c47..cd52d50 100644 --- a/communication/auth/service.go +++ b/communication/auth/service.go @@ -1,11 +1,13 @@ package auth import ( + "encoding/json" "fmt" "github.com/iden3/go-iden3-auth/communication/protocol" "github.com/iden3/go-iden3-auth/proofs/signature" "github.com/iden3/go-iden3-auth/proofs/zeroknowledge" "github.com/iden3/go-iden3-auth/types" + "github.com/pkg/errors" ) const ( @@ -36,10 +38,26 @@ func Verify(message types.Message) (err error) { if message.GetType() != AuthorizationResponseMessageType { return fmt.Errorf("%s doesn't support %s message type", Name, (message).GetType()) } - authorizationContent := message.GetData().(types.AuthorizationMessageResponseData) - for _, s := range authorizationContent.Scope { - switch proof := s.(type) { + var authorizationResponseData types.AuthorizationMessageResponseData + + switch message.GetData().(type) { + case json.RawMessage: + err = json.Unmarshal(message.GetData().(json.RawMessage), &authorizationResponseData) + if err != nil { + return err + } + case types.AuthorizationMessageResponseData: + authorizationResponseData = message.GetData().(types.AuthorizationMessageResponseData) + } + + for _, s := range authorizationResponseData.Scope { + var typedScope types.TypedScope + typedScope, err = toTypedScope(s) + if err != nil { + return err + } + switch proof := typedScope.(type) { case types.ZeroKnowledgeProof: err = zeroknowledge.VerifyProof(&proof) if err != nil { @@ -50,6 +68,9 @@ func Verify(message types.Message) (err error) { if err != nil { return fmt.Errorf("proof with type %s is not valid. %s", proof.Type, err.Error()) } + default: + fmt.Println(proof) + return errors.New("unknown proof") } // TODO: throw error on unknown proof } @@ -61,12 +82,27 @@ func ExtractMetadata(message types.Message) (token *UserToken, err error) { if message.GetType() != AuthorizationResponseMessageType { return nil, fmt.Errorf("%s doesn't support %s message type", Name, message.GetType()) } - authorizationContent := message.GetData().(types.AuthorizationMessageResponseData) + var authorizationResponseData types.AuthorizationMessageResponseData + switch message.GetData().(type) { + case json.RawMessage: + err = json.Unmarshal(message.GetData().(json.RawMessage), &authorizationResponseData) + if err != nil { + return nil, err + } + case types.AuthorizationMessageResponseData: + authorizationResponseData = message.GetData().(types.AuthorizationMessageResponseData) + } token = &UserToken{} token.Scope = map[string]map[string]interface{}{} - for _, s := range authorizationContent.Scope { - switch proof := s.(type) { + for _, s := range authorizationResponseData.Scope { + + var typedScope types.TypedScope + typedScope, err = toTypedScope(s) + if err != nil { + return nil, err + } + switch proof := typedScope.(type) { case types.ZeroKnowledgeProof: err = zeroknowledge.ExtractMetadata(&proof) if err != nil { @@ -88,9 +124,42 @@ func ExtractMetadata(message types.Message) (token *UserToken, err error) { return nil, fmt.Errorf("can't provide user token %s", err.Error()) } } - - // TODO: throw error on unknown proof - } return token, nil } + +func toTypedScope(value interface{}) (types.TypedScope, error) { + switch obj := value.(type) { + case map[string]interface{}: + scopeMap, ok := value.(map[string]interface{}) + if !ok { + return nil, errors.New("scope object is not a map") + } + b, err := json.Marshal(value) + if err != nil { + return nil, errors.Wrap(err, "can't marshall scope obj") + } + switch types.ProofType(scopeMap["type"].(string)) { + case types.ZeroKnowledgeProofType: + var zkp types.ZeroKnowledgeProof + err = json.Unmarshal(b, &zkp) + if err != nil { + return nil, errors.Wrap(err, "can't unmarshall to zkp proof") + } + return zkp, nil + case types.SignatureProofType: + var sig types.SignatureProof + err = json.Unmarshal(b, &sig) + if err != nil { + return nil, errors.Wrap(err, "can't unmarshall to signature proof") + } + return sig, nil + default: + return nil, errors.Errorf("proof type is not supported: %s ", scopeMap["type"]) + } + case types.TypedScope: + return obj, nil + default: + return nil, errors.Errorf("scope object type is not supported %v", value) + } +} diff --git a/communication/auth/service_test.go b/communication/auth/service_test.go index 62c62b7..cebfa7c 100644 --- a/communication/auth/service_test.go +++ b/communication/auth/service_test.go @@ -65,7 +65,7 @@ func TestVerify(t *testing.T) { "25", "18", } - message.Data.Scope = []types.TypedScope{zkpProof} + message.Data.Scope = []interface{}{zkpProof} err := Verify(&message) assert.Nil(t, err) @@ -182,7 +182,7 @@ func TestExtractData(t *testing.T) { }, } - message.Data.Scope = []types.TypedScope{zkpProof} + message.Data.Scope = []interface{}{zkpProof} token, err := ExtractMetadata(&message) assert.Nil(t, err) @@ -230,7 +230,7 @@ func TestVerifyMessageWithAuthProof(t *testing.T) { "12345", "16751774198505232045539489584666775489135471631443877047826295522719290880931", } - message.Data.Scope = []types.TypedScope{zkpProof} + message.Data.Scope = []interface{}{zkpProof} err := Verify(&message) assert.Nil(t, err) diff --git a/communication/packer/plain_test.go b/communication/packer/plain_test.go index 1c8e5ad..a7b33b9 100644 --- a/communication/packer/plain_test.go +++ b/communication/packer/plain_test.go @@ -37,10 +37,17 @@ func TestPlainMessagePacker_Pack(t *testing.T) { func TestPlainMessagePacker_Unpack(t *testing.T) { packer := PlainMessagePacker{} - msgBytes := []byte(`{"type":"https://iden3-communication.io/authorization-request/v1","data":{"callbackUrl":"https://test.com","audience":"1125GJqgw6YEsKFwj63GY87MMxPL9kwDKxPUiwMLNZ","scope":[{"circuit_id":"kycBySignatures","type":"zeroknowledge","rules":{"challenge":"1234567"}}]}}`) + msgBytes := []byte(`{"type":"https://iden3-communication.io/authorization-response/v1","data":{"scope":[{"type":"zeroknowledge","circuit_id":"auth","pub_signals":["371135506535866236563870411357090963344408827476607986362864968105378316288","12345","16751774198505232045539489584666775489135471631443877047826295522719290880931"],"proof_data":{"pi_a":["8286889681087188684411199510889276918687181609540093440568310458198317956303","20120810686068956496055592376395897424117861934161580256832624025185006492545","1"],"pi_b":[["8781021494687726640921078755116610543888920881180197598360798979078295904948","19202155147447713148677957576892776380573753514701598304555554559013661311518"],["15726655173394887666308034684678118482468533753607200826879522418086507576197","16663572050292231627606042532825469225281493999513959929720171494729819874292"],["1","0"]],"pi_c":["9723779257940517259310236863517792034982122114581325631102251752415874164616","3242951480985471018890459433562773969741463856458716743271162635077379852479","1"],"protocol":"groth16"}}]}}`) message, err := packer.Unpack(msgBytes) assert.Nil(t, err) - assert.Equal(t, auth.AuthorizationRequestMessageType, message.GetType()) + assert.Equal(t, auth.AuthorizationResponseMessageType, message.GetType()) + + err = auth.Verify(message) + assert.Nil(t, err) + + token, err := auth.ExtractMetadata(message) + assert.Nil(t, err) + assert.Equal(t, "11A2HgCZ1pUcY8HoNDMjNWEBQXZdUnL3YVnVCUvR5s", token.ID) } func TestPlainMessagePacker_PackAuthorizationResponse(t *testing.T) { @@ -72,7 +79,7 @@ func TestPlainMessagePacker_PackAuthorizationResponse(t *testing.T) { "383481829333688262229762912714748186426235428103586432827469388069546950656", "12345", } - message.Data.Scope = []types2.TypedScope{zkpProof} + message.Data.Scope = []interface{}{zkpProof} msgBytes, err := packer.Pack("application/json", &message) t.Log(string(msgBytes)) diff --git a/go.mod b/go.mod index f8d8a5f..2e6dc58 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/go-stack/stack v1.8.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/iden3/go-iden3-crypto v0.0.11 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect diff --git a/go.sum b/go.sum index 11d64dc..15523dd 100644 --- a/go.sum +++ b/go.sum @@ -311,6 +311,8 @@ github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4f github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/types/message.go b/types/message.go index 08ae83b..dc73772 100644 --- a/types/message.go +++ b/types/message.go @@ -16,7 +16,7 @@ type Message interface { // BasicMessage is structure for message with unknown data format type BasicMessage struct { Type ProtocolMessage `json:"type"` - Data interface{} + Data json.RawMessage `json:"data"` Message } @@ -39,7 +39,7 @@ type AuthorizationMessageRequestData struct { // AuthorizationMessageResponseData is struct the represents authorization response data type AuthorizationMessageResponseData struct { - Scope []TypedScope `json:"scope"` + Scope []interface{} `json:"scope"` } // TypedScope is interface that restricts objects that can be used for scope in authorization request