-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add Kleros identity provider * rework identity providers credential subject * fix Kleros config * fix Kleros metadata * add Kleros to the config * fix CI * return 401 Unauthorized if user is not registered in Kleros * minor fix * fix errors lib
- Loading branch information
1 parent
a2262f1
commit e82d58f
Showing
19 changed files
with
4,063 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
type: object | ||
description: Kleros provider's data | ||
required: | ||
- address | ||
- signature | ||
properties: | ||
address: | ||
type: string | ||
format: string | ||
description: The user's address | ||
example: '0x1234567890123456789012345678901234567890' | ||
signature: | ||
type: string | ||
format: string | ||
description: >- | ||
The signature of the requested nonce to validate if the user owns the | ||
address | ||
example: >- | ||
0x1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package config | ||
|
||
import ( | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/ethclient" | ||
"gitlab.com/distributed_lab/figure" | ||
"gitlab.com/distributed_lab/kit/kv" | ||
"gitlab.com/distributed_lab/logan/v3/errors" | ||
) | ||
|
||
type Kleros struct { | ||
EthereumRpc *ethclient.Client | ||
ProofOfHumanityContract common.Address | ||
} | ||
|
||
type kleros struct { | ||
EthRpcURL string `fig:"eth_rpc_url,required"` | ||
ProofOfHumanityContract string `fig:"proof_of_humanity_contract,required"` | ||
} | ||
|
||
func (c *config) Kleros() *Kleros { | ||
return c.kleros.Do(func() interface{} { | ||
cfg := kleros{} | ||
err := figure. | ||
Out(&cfg). | ||
From(kv.MustGetStringMap(c.getter, "kleros")). | ||
Please() | ||
if err != nil { | ||
panic(errors.Wrap(err, "failed to figure out")) | ||
} | ||
|
||
return parseKlerosConfig(&cfg) | ||
}).(*Kleros) | ||
} | ||
|
||
func parseKlerosConfig(cfg *kleros) *Kleros { | ||
ethClient, err := ethclient.Dial(cfg.EthRpcURL) | ||
if err != nil { | ||
panic(errors.Wrap(err, "failed to create an Ethereum client")) | ||
} | ||
|
||
if !common.IsHexAddress(cfg.ProofOfHumanityContract) { | ||
panic(errors.New("failed to parse gateway token contract address")) | ||
} | ||
|
||
return &Kleros{ | ||
EthereumRpc: ethClient, | ||
ProofOfHumanityContract: common.HexToAddress(cfg.ProofOfHumanityContract), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3,729 changes: 3,729 additions & 0 deletions
3,729
internal/service/core/identity_providers/kleros/contracts/proof_of_humanity.go
Large diffs are not rendered by default.
Oops, something went wrong.
119 changes: 119 additions & 0 deletions
119
internal/service/core/identity_providers/kleros/main.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package kleros | ||
|
||
import ( | ||
"encoding/json" | ||
"time" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
cryptoPkg "github.com/ethereum/go-ethereum/crypto" | ||
"github.com/pkg/errors" | ||
"gitlab.com/distributed_lab/logan/v3" | ||
|
||
"github.com/rarimo/kyc-service/internal/config" | ||
"github.com/rarimo/kyc-service/internal/crypto" | ||
"github.com/rarimo/kyc-service/internal/data" | ||
providers "github.com/rarimo/kyc-service/internal/service/core/identity_providers" | ||
"github.com/rarimo/kyc-service/internal/service/core/identity_providers/kleros/contracts" | ||
"github.com/rarimo/kyc-service/internal/service/core/issuer" | ||
) | ||
|
||
type Kleros struct { | ||
logger *logan.Entry | ||
masterQ data.MasterQ | ||
proofOfHumanityContract *contracts.ProofOfHumanity | ||
} | ||
|
||
func NewIdentityProvider( | ||
logger *logan.Entry, masterQ data.MasterQ, config *config.Kleros, | ||
) (*Kleros, error) { | ||
pohContract, err := contracts.NewProofOfHumanity(config.ProofOfHumanityContract, config.EthereumRpc) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed to create proof of humanity contract") | ||
} | ||
|
||
return &Kleros{ | ||
logger: logger, | ||
masterQ: masterQ, | ||
proofOfHumanityContract: pohContract, | ||
}, nil | ||
} | ||
|
||
func (k *Kleros) Verify( | ||
user *data.User, verifyDataRaw []byte, | ||
) (*issuer.IdentityProvidersCredentialSubject, []byte, error) { | ||
var verifyData VerificationData | ||
if err := json.Unmarshal(verifyDataRaw, &verifyData); err != nil { | ||
return nil, nil, errors.Wrap(err, "failed to unmarshal verification data") | ||
} | ||
|
||
if err := verifyData.Validate(); err != nil { | ||
return nil, nil, providers.ErrInvalidVerificationData | ||
} | ||
|
||
userAddr := common.HexToAddress(verifyData.Address) | ||
|
||
if err := k.verifySignature(verifyData.Signature, userAddr); err != nil { | ||
return nil, nil, errors.Wrap(err, "failed to verify signature") | ||
} | ||
|
||
if err := k.checkIfIsRegistered(userAddr); err != nil { | ||
return nil, nil, errors.Wrap(err, "failed to check if user is registered") | ||
} | ||
|
||
providerDataRaw, err := json.Marshal(ProviderData{ | ||
Address: userAddr, | ||
}) | ||
if err != nil { | ||
return nil, nil, errors.Wrap(err, "failed to marshal provider data") | ||
} | ||
|
||
user.EthAddress = &userAddr | ||
user.Status = data.UserStatusVerified | ||
user.ProviderData = providerDataRaw | ||
|
||
credentialSubject := issuer.NewEmptyIdentityProvidersCredentialSubject() | ||
credentialSubject.Provider = issuer.KlerosProviderName | ||
credentialSubject.Address = userAddr.String() | ||
credentialSubject.ProviderMetadata = "none" | ||
|
||
return credentialSubject, cryptoPkg.Keccak256( | ||
userAddr.Bytes(), | ||
providers.KlerosIdentityProvider.Bytes(), | ||
), nil | ||
} | ||
|
||
// verifySignature verifies user's signature | ||
func (k *Kleros) verifySignature(signature string, userAddr common.Address) error { | ||
nonce, err := k.masterQ.NonceQ(). | ||
WhereEthAddress(userAddr). | ||
WhereExpiresAtGt(time.Now()). | ||
Get() | ||
if err != nil { | ||
return errors.Wrap(err, "failed to get nonce") | ||
} | ||
if nonce == nil { | ||
return providers.ErrNonceNotFound | ||
} | ||
|
||
valid, err := crypto.VerifyEIP191Signature( | ||
signature, | ||
crypto.NonceToSignMessage(nonce.Nonce), | ||
userAddr, | ||
) | ||
if err != nil || !valid { | ||
return providers.ErrInvalidUsersSignature | ||
} | ||
|
||
return errors.Wrap(k.masterQ.NonceQ().WhereEthAddress(userAddr).Delete(), "failed to delete nonce") | ||
} | ||
|
||
func (k *Kleros) checkIfIsRegistered(userAddress common.Address) error { | ||
isRegistered, err := k.proofOfHumanityContract.IsRegistered(nil, userAddress) | ||
if err != nil { | ||
return errors.Wrap(err, "failed to call isRegistered contract method") | ||
} | ||
if !isRegistered { | ||
return ErrIsNotRegistered | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package kleros | ||
|
||
import ( | ||
"github.com/ethereum/go-ethereum/common" | ||
validation "github.com/go-ozzo/ozzo-validation/v4" | ||
"github.com/pkg/errors" | ||
|
||
"github.com/rarimo/kyc-service/internal/service/api/requests" | ||
"github.com/rarimo/kyc-service/resources" | ||
) | ||
|
||
var ErrIsNotRegistered = errors.New("user is not registered") | ||
|
||
type ( | ||
// VerificationData is a data that is required by Kleros to verify a user | ||
VerificationData resources.KlerosData | ||
) | ||
|
||
type ProviderData struct { | ||
Address common.Address `json:"address"` | ||
} | ||
|
||
// Validate is a method that validates VerificationData | ||
func (v VerificationData) Validate() error { | ||
return validation.Errors{ | ||
"signature": validation.Validate(v.Signature, validation.Required), | ||
"address": validation.Validate(v.Address, validation.Required, validation.By(requests.MustBeEthAddress)), | ||
}.Filter() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.