mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-03 18:01:39 +00:00
feature/refactor did state (#10)
* feat(did): remove account types * feat: Refactor Property to Proof in zkprop.go * feat: add ZKP proof mechanism for verifications * fix: return bool and error from pinInitialVault * feat: implement KeyshareSet for managing user and validator keyshares * feat: Update Credential type in protobuf * feat: update credential schema with sign count * feat: migrate and modules to middleware * refactor: rename vault module to ORM * chore(dwn): add service worker registration to index template * feat: integrate service worker for offline functionality * refactor(did): use DIDNamespace enum for verification method in proto reflection * refactor: update protobuf definitions to support Keyshare * feat: expose did keeper in app keepers * Add Motr Web App * refactor: rename motr/handlers/discovery.go to motr/handlers/openid.go * refactor: move session related code to middleware * feat: add database operations for managing assets, chains, and credentials * feat: add htmx support for UI updates * refactor: extract common helper scripts * chore: remove unused storage GUI components * refactor: Move frontend rendering to dedicated handlers * refactor: rename to * refactor: move alert implementation to templ * feat: add alert component with icon, title, and message * feat: add new RequestHeaders struct to store request headers * Feature/create home view (#9) * refactor: move view logic to new htmx handler * refactor: remove unnecessary dependencies * refactor: remove unused dependencies * feat(devbox): integrate air for local development * feat: implement openid connect discovery document * refactor: rename to * refactor(did): update service handling to support DNS discovery * feat: add support for user and validator keyshares * refactor: move keyshare signing logic to signer
This commit is contained in:
+148
-73
@@ -4,12 +4,103 @@ import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol/webauthncose"
|
||||
didv1 "github.com/onsonr/sonr/api/did/v1"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
func FormatEC2PublicKey(key *webauthncose.EC2PublicKeyData) (*types.JWK, error) {
|
||||
func APIFormatDIDNamespace(namespace types.DIDNamespace) didv1.DIDNamespace {
|
||||
return didv1.DIDNamespace(namespace)
|
||||
}
|
||||
|
||||
func APIFormatDIDNamespaces(namespaces []types.DIDNamespace) []didv1.DIDNamespace {
|
||||
var s []didv1.DIDNamespace
|
||||
for _, namespace := range namespaces {
|
||||
s = append(s, APIFormatDIDNamespace(namespace))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func APIFormatKeyRole(role types.KeyRole) didv1.KeyRole {
|
||||
return didv1.KeyRole(role)
|
||||
}
|
||||
|
||||
func APIFormatKeyAlgorithm(algorithm types.KeyAlgorithm) didv1.KeyAlgorithm {
|
||||
return didv1.KeyAlgorithm(algorithm)
|
||||
}
|
||||
|
||||
func APIFormatKeyEncoding(encoding types.KeyEncoding) didv1.KeyEncoding {
|
||||
return didv1.KeyEncoding(encoding)
|
||||
}
|
||||
|
||||
func APIFormatKeyCurve(curve types.KeyCurve) didv1.KeyCurve {
|
||||
return didv1.KeyCurve(curve)
|
||||
}
|
||||
|
||||
func APIFormatKeyType(keyType types.KeyType) didv1.KeyType {
|
||||
return didv1.KeyType(keyType)
|
||||
}
|
||||
|
||||
func APIFormatPermissions(permissions *types.Permissions) *didv1.Permissions {
|
||||
if permissions == nil {
|
||||
return nil
|
||||
}
|
||||
p := didv1.Permissions{
|
||||
Grants: APIFormatDIDNamespaces(permissions.Grants),
|
||||
Scopes: APIFormatPermissionScopes(permissions.Scopes),
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
||||
func APIFormatPermissionScope(scope types.PermissionScope) didv1.PermissionScope {
|
||||
return didv1.PermissionScope(scope)
|
||||
}
|
||||
|
||||
func APIFormatPermissionScopes(scopes []types.PermissionScope) []didv1.PermissionScope {
|
||||
var s []didv1.PermissionScope
|
||||
for _, scope := range scopes {
|
||||
s = append(s, APIFormatPermissionScope(scope))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func APIFormatServiceRecord(service *types.Service) *didv1.ServiceRecord {
|
||||
return &didv1.ServiceRecord{
|
||||
Id: service.Id,
|
||||
ServiceType: service.ServiceType,
|
||||
Authority: service.Authority,
|
||||
Origin: service.Origin,
|
||||
Description: service.Description,
|
||||
ServiceEndpoints: service.ServiceEndpoints,
|
||||
Permissions: APIFormatPermissions(service.Permissions),
|
||||
}
|
||||
}
|
||||
|
||||
func APIFormatPubKeyJWK(jwk *types.PubKey_JWK) *didv1.PubKey_JWK {
|
||||
return &didv1.PubKey_JWK{
|
||||
Kty: jwk.Kty,
|
||||
Crv: jwk.Crv,
|
||||
X: jwk.X,
|
||||
Y: jwk.Y,
|
||||
N: jwk.N,
|
||||
E: jwk.E,
|
||||
}
|
||||
}
|
||||
|
||||
func APIFormatPubKey(key *types.PubKey) *didv1.PubKey {
|
||||
return &didv1.PubKey{
|
||||
Role: APIFormatKeyRole(key.GetRole()),
|
||||
Algorithm: APIFormatKeyAlgorithm(key.GetAlgorithm()),
|
||||
Encoding: APIFormatKeyEncoding(key.GetEncoding()),
|
||||
Curve: APIFormatKeyCurve(key.GetCurve()),
|
||||
KeyType: APIFormatKeyType(key.GetKeyType()),
|
||||
Raw: key.GetRaw(),
|
||||
}
|
||||
}
|
||||
|
||||
func FormatEC2PublicKey(key *webauthncose.EC2PublicKeyData) (*types.PubKey_JWK, error) {
|
||||
curve, err := GetCOSECurveName(key.Curve)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -25,7 +116,7 @@ func FormatEC2PublicKey(key *webauthncose.EC2PublicKeyData) (*types.JWK, error)
|
||||
return MapToJWK(jwkMap)
|
||||
}
|
||||
|
||||
func FormatRSAPublicKey(key *webauthncose.RSAPublicKeyData) (*types.JWK, error) {
|
||||
func FormatRSAPublicKey(key *webauthncose.RSAPublicKeyData) (*types.PubKey_JWK, error) {
|
||||
jwkMap := map[string]interface{}{
|
||||
"kty": "RSA",
|
||||
"n": base64.RawURLEncoding.EncodeToString(key.Modulus),
|
||||
@@ -35,8 +126,8 @@ func FormatRSAPublicKey(key *webauthncose.RSAPublicKeyData) (*types.JWK, error)
|
||||
return MapToJWK(jwkMap)
|
||||
}
|
||||
|
||||
func FormatOKPPublicKey(key *webauthncose.OKPPublicKeyData) (*types.JWK, error) {
|
||||
curve, err := getOKPCurveName(key.Curve)
|
||||
func FormatOKPPublicKey(key *webauthncose.OKPPublicKeyData) (*types.PubKey_JWK, error) {
|
||||
curve, err := GetOKPCurveName(key.Curve)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -50,8 +141,8 @@ func FormatOKPPublicKey(key *webauthncose.OKPPublicKeyData) (*types.JWK, error)
|
||||
return MapToJWK(jwkMap)
|
||||
}
|
||||
|
||||
func MapToJWK(m map[string]interface{}) (*types.JWK, error) {
|
||||
jwk := &types.JWK{}
|
||||
func MapToJWK(m map[string]interface{}) (*types.PubKey_JWK, error) {
|
||||
jwk := &types.PubKey_JWK{}
|
||||
for k, v := range m {
|
||||
switch k {
|
||||
case "kty":
|
||||
@@ -84,7 +175,7 @@ func GetCOSECurveName(curveID int64) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func getOKPCurveName(curveID int64) (string, error) {
|
||||
func GetOKPCurveName(curveID int64) (string, error) {
|
||||
switch curveID {
|
||||
case int64(webauthncose.Ed25519):
|
||||
return "Ed25519", nil
|
||||
@@ -93,84 +184,68 @@ func getOKPCurveName(curveID int64) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func ModulePubKeyToAPI(pk *types.PubKey) *didv1.PubKey {
|
||||
return &didv1.PubKey{
|
||||
Role: ModuleKeyRoleToAPI(pk.GetRole()),
|
||||
Algorithm: ModuleKeyAlgorithmToAPI(pk.GetAlgorithm()),
|
||||
Encoding: ModuleKeyEncodingToAPI(pk.GetEncoding()),
|
||||
Curve: ModuleKeyCurveToAPI(pk.GetCurve()),
|
||||
KeyType: ModuleKeyTypeToAPI(pk.GetKeyType()),
|
||||
Raw: pk.GetRaw(),
|
||||
// NormalizeTransports returns the transports as strings
|
||||
func NormalizeTransports(transports []protocol.AuthenticatorTransport) []string {
|
||||
tss := make([]string, len(transports))
|
||||
for i, t := range transports {
|
||||
tss[i] = string(t)
|
||||
}
|
||||
return tss
|
||||
}
|
||||
|
||||
// GetTransports returns the protocol.AuthenticatorTransport
|
||||
func ModuleTransportsToProtocol(transport []string) []protocol.AuthenticatorTransport {
|
||||
tss := make([]protocol.AuthenticatorTransport, len(transport))
|
||||
for i, t := range transport {
|
||||
tss[i] = protocol.AuthenticatorTransport(t)
|
||||
}
|
||||
return tss
|
||||
}
|
||||
|
||||
// ModuleFormatAPIServiceRecord formats a service record for the module
|
||||
func ModuleFormatAPIServiceRecord(service *didv1.ServiceRecord) *types.Service {
|
||||
return &types.Service{
|
||||
Id: service.Id,
|
||||
ServiceType: service.ServiceType,
|
||||
Authority: service.Authority,
|
||||
Origin: service.Origin,
|
||||
Description: service.Description,
|
||||
ServiceEndpoints: service.ServiceEndpoints,
|
||||
Permissions: ModuleFormatAPIPermissions(service.Permissions),
|
||||
}
|
||||
}
|
||||
|
||||
func ModuleKeyRoleToAPI(role types.KeyRole) didv1.KeyRole {
|
||||
switch role {
|
||||
case types.KeyRole_KEY_ROLE_INVOCATION:
|
||||
return didv1.KeyRole_KEY_ROLE_INVOCATION
|
||||
case types.KeyRole_KEY_ROLE_ASSERTION:
|
||||
return didv1.KeyRole_KEY_ROLE_ASSERTION
|
||||
case types.KeyRole_KEY_ROLE_DELEGATION:
|
||||
return didv1.KeyRole_KEY_ROLE_DELEGATION
|
||||
default:
|
||||
return didv1.KeyRole_KEY_ROLE_INVOCATION
|
||||
func ModuleFormatAPIPermissions(permissions *didv1.Permissions) *types.Permissions {
|
||||
if permissions == nil {
|
||||
return nil
|
||||
}
|
||||
p := types.Permissions{
|
||||
Grants: ModuleFormatAPIDIDNamespaces(permissions.Grants),
|
||||
Scopes: ModuleFormatAPIPermissionScopes(permissions.Scopes),
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
||||
func ModuleKeyAlgorithmToAPI(algorithm types.KeyAlgorithm) didv1.KeyAlgorithm {
|
||||
switch algorithm {
|
||||
case types.KeyAlgorithm_KEY_ALGORITHM_ES256K:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_ES256K
|
||||
case types.KeyAlgorithm_KEY_ALGORITHM_ES256:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_ES256
|
||||
case types.KeyAlgorithm_KEY_ALGORITHM_ES384:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_ES384
|
||||
case types.KeyAlgorithm_KEY_ALGORITHM_ES512:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_ES512
|
||||
case types.KeyAlgorithm_KEY_ALGORITHM_EDDSA:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_EDDSA
|
||||
default:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_ES256K
|
||||
}
|
||||
func ModuleFormatAPIPermissionScope(scope didv1.PermissionScope) types.PermissionScope {
|
||||
return types.PermissionScope(scope)
|
||||
}
|
||||
|
||||
func ModuleKeyCurveToAPI(curve types.KeyCurve) didv1.KeyCurve {
|
||||
switch curve {
|
||||
case types.KeyCurve_KEY_CURVE_P256:
|
||||
return didv1.KeyCurve_KEY_CURVE_P256
|
||||
case types.KeyCurve_KEY_CURVE_SECP256K1:
|
||||
return didv1.KeyCurve_KEY_CURVE_SECP256K1
|
||||
case types.KeyCurve_KEY_CURVE_BLS12381:
|
||||
return didv1.KeyCurve_KEY_CURVE_BLS12381
|
||||
case types.KeyCurve_KEY_CURVE_KECCAK256:
|
||||
return didv1.KeyCurve_KEY_CURVE_KECCAK256
|
||||
default:
|
||||
return didv1.KeyCurve_KEY_CURVE_P256
|
||||
func ModuleFormatAPIPermissionScopes(scopes []didv1.PermissionScope) []types.PermissionScope {
|
||||
var s []types.PermissionScope
|
||||
for _, scope := range scopes {
|
||||
s = append(s, ModuleFormatAPIPermissionScope(scope))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func ModuleKeyEncodingToAPI(encoding types.KeyEncoding) didv1.KeyEncoding {
|
||||
switch encoding {
|
||||
case types.KeyEncoding_KEY_ENCODING_RAW:
|
||||
return didv1.KeyEncoding_KEY_ENCODING_RAW
|
||||
case types.KeyEncoding_KEY_ENCODING_HEX:
|
||||
return didv1.KeyEncoding_KEY_ENCODING_HEX
|
||||
case types.KeyEncoding_KEY_ENCODING_MULTIBASE:
|
||||
return didv1.KeyEncoding_KEY_ENCODING_MULTIBASE
|
||||
default:
|
||||
return didv1.KeyEncoding_KEY_ENCODING_RAW
|
||||
}
|
||||
func ModuleFormatAPIDIDNamespace(namespace didv1.DIDNamespace) types.DIDNamespace {
|
||||
return types.DIDNamespace(namespace)
|
||||
}
|
||||
|
||||
func ModuleKeyTypeToAPI(keyType types.KeyType) didv1.KeyType {
|
||||
switch keyType {
|
||||
case types.KeyType_KEY_TYPE_BIP32:
|
||||
return didv1.KeyType_KEY_TYPE_BIP32
|
||||
case types.KeyType_KEY_TYPE_ZK:
|
||||
return didv1.KeyType_KEY_TYPE_ZK
|
||||
case types.KeyType_KEY_TYPE_WEBAUTHN:
|
||||
return didv1.KeyType_KEY_TYPE_WEBAUTHN
|
||||
default:
|
||||
return didv1.KeyType_KEY_TYPE_BIP32
|
||||
func ModuleFormatAPIDIDNamespaces(namespaces []didv1.DIDNamespace) []types.DIDNamespace {
|
||||
var s []types.DIDNamespace
|
||||
for _, namespace := range namespaces {
|
||||
s = append(s, ModuleFormatAPIDIDNamespace(namespace))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gopkg.in/macaroon.v2"
|
||||
|
||||
"gopkg.in/macaroon-bakery.v2/bakery/checkers"
|
||||
)
|
||||
|
||||
var PermissionNamespace *checkers.Namespace
|
||||
|
||||
func ValidateMacaroonMiddleware(secretKey []byte, location string) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
// Extract the macaroon from the Authorization header
|
||||
auth := c.Request().Header.Get("Authorization")
|
||||
if auth == "" {
|
||||
return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Missing Authorization header"})
|
||||
}
|
||||
|
||||
// Decode the macaroon
|
||||
mac, err := macaroon.Base64Decode([]byte(auth))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid macaroon encoding"})
|
||||
}
|
||||
|
||||
token, err := macaroon.New(secretKey, mac, location, macaroon.LatestVersion)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid macaroon"})
|
||||
}
|
||||
|
||||
// Verify the macaroon
|
||||
err = token.Verify(secretKey, func(caveat string) error {
|
||||
// Implement your caveat verification logic here
|
||||
// For example, you might check if the caveat is still valid (e.g., not expired)
|
||||
return nil // Return nil if the caveat is valid
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Invalid macaroon"})
|
||||
}
|
||||
|
||||
// Macaroon is valid, proceed to the next handler
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ type PublicKeyCredentialCreationOptions struct {
|
||||
Extensions AuthenticationExtensions `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
func NewRegistrationOptions(origin string, subject string, vaultCID string, params *types.Params) (*PublicKeyCredentialCreationOptions, error) {
|
||||
func GetPublicKeyCredentialCreationOptions(origin string, subject string, vaultCID string, params *types.Params) (*PublicKeyCredentialCreationOptions, error) {
|
||||
chal, err := CreateChallenge()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
didv1 "github.com/onsonr/sonr/api/did/v1"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol/webauthncose"
|
||||
@@ -33,17 +34,17 @@ func CreateAuthnVerification(namespace types.DIDNamespace, issuer string, contro
|
||||
}
|
||||
|
||||
// CreateWalletVerification creates a new verification method for a wallet
|
||||
func CreateWalletVerification(namespace types.DIDNamespace, controller string, pubkey *types.PubKey, identifier string) *types.VerificationMethod {
|
||||
return &types.VerificationMethod{
|
||||
Method: namespace,
|
||||
func CreateWalletVerification(namespace types.DIDNamespace, controller string, pubkey *types.PubKey, identifier string) *didv1.VerificationMethod {
|
||||
return &didv1.VerificationMethod{
|
||||
Method: APIFormatDIDNamespace(namespace),
|
||||
Controller: controller,
|
||||
PublicKey: pubkey,
|
||||
PublicKey: APIFormatPubKey(pubkey),
|
||||
Id: identifier,
|
||||
}
|
||||
}
|
||||
|
||||
// ExtractWebAuthnPublicKey parses the raw public key bytes and returns a JWK representation
|
||||
func ExtractWebAuthnPublicKey(keyBytes []byte) (*types.JWK, error) {
|
||||
func ExtractWebAuthnPublicKey(keyBytes []byte) (*types.PubKey_JWK, error) {
|
||||
key, err := webauthncose.ParsePublicKey(keyBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse public key: %w", err)
|
||||
@@ -62,8 +63,8 @@ func ExtractWebAuthnPublicKey(keyBytes []byte) (*types.JWK, error) {
|
||||
}
|
||||
|
||||
// NewInitialWalletAccounts creates a new set of verification methods for a wallet
|
||||
func NewInitialWalletAccounts(controller string, pubkey *types.PubKey) ([]*types.VerificationMethod, error) {
|
||||
var verificationMethods []*types.VerificationMethod
|
||||
func NewInitialWalletAccounts(controller string, pubkey *types.PubKey) ([]*didv1.VerificationMethod, error) {
|
||||
var verificationMethods []*didv1.VerificationMethod
|
||||
for method, chain := range types.InitialChainCodes {
|
||||
nk, err := computeBip32AccountPublicKey(pubkey, chain, 0)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery/checkers"
|
||||
)
|
||||
|
||||
var (
|
||||
GenericPermissionScopeStrings = [...]string{
|
||||
"profile.name",
|
||||
"identifiers.email",
|
||||
"identifiers.phone",
|
||||
"transactions.read",
|
||||
"transactions.write",
|
||||
"wallets.read",
|
||||
"wallets.create",
|
||||
"wallets.subscribe",
|
||||
"wallets.update",
|
||||
"transactions.verify",
|
||||
"transactions.broadcast",
|
||||
"admin.user",
|
||||
"admin.validator",
|
||||
}
|
||||
|
||||
StringToModulePermissionScope = map[string]types.PermissionScope{
|
||||
"PERMISSION_SCOPE_UNSPECIFIED": types.PermissionScope_PERMISSION_SCOPE_UNSPECIFIED,
|
||||
"PERMISSION_SCOPE_BASIC_INFO": types.PermissionScope_PERMISSION_SCOPE_BASIC_INFO,
|
||||
"PERMISSION_SCOPE_IDENTIFIERS_EMAIL": types.PermissionScope_PERMISSION_SCOPE_PERMISSIONS_READ,
|
||||
"PERMISSION_SCOPE_IDENTIFIERS_PHONE": types.PermissionScope_PERMISSION_SCOPE_PERMISSIONS_WRITE,
|
||||
"PERMISSION_SCOPE_TRANSACTIONS_READ": types.PermissionScope_PERMISSION_SCOPE_TRANSACTIONS_READ,
|
||||
"PERMISSION_SCOPE_TRANSACTIONS_WRITE": types.PermissionScope_PERMISSION_SCOPE_TRANSACTIONS_WRITE,
|
||||
"PERMISSION_SCOPE_WALLETS_READ": types.PermissionScope_PERMISSION_SCOPE_WALLETS_READ,
|
||||
"PERMISSION_SCOPE_WALLETS_CREATE": types.PermissionScope_PERMISSION_SCOPE_WALLETS_CREATE,
|
||||
"PERMISSION_SCOPE_WALLETS_SUBSCRIBE": types.PermissionScope_PERMISSION_SCOPE_WALLETS_SUBSCRIBE,
|
||||
"PERMISSION_SCOPE_WALLETS_UPDATE": types.PermissionScope_PERMISSION_SCOPE_WALLETS_UPDATE,
|
||||
"PERMISSION_SCOPE_TRANSACTIONS_VERIFY": types.PermissionScope_PERMISSION_SCOPE_TRANSACTIONS_VERIFY,
|
||||
"PERMISSION_SCOPE_TRANSACTIONS_BROADCAST": types.PermissionScope_PERMISSION_SCOPE_TRANSACTIONS_BROADCAST,
|
||||
"PERMISSION_SCOPE_ADMIN_USER": types.PermissionScope_PERMISSION_SCOPE_ADMIN_USER,
|
||||
"PERMISSION_SCOPE_ADMIN_VALIDATOR": types.PermissionScope_PERMISSION_SCOPE_ADMIN_VALIDATOR,
|
||||
}
|
||||
)
|
||||
|
||||
func ResolvePermissionScope(scope string) (types.PermissionScope, bool) {
|
||||
uriToPrefix := make(map[string]string)
|
||||
for _, scope := range GenericPermissionScopeStrings {
|
||||
uriToPrefix["https://example.com/auth/"+scope] = scope
|
||||
}
|
||||
PermissionNamespace := checkers.NewNamespace(uriToPrefix)
|
||||
|
||||
prefix, ok := PermissionNamespace.Resolve("https://example.com/auth/" + scope)
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
permScope, ok := StringToModulePermissionScope[prefix]
|
||||
return permScope, ok
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"github.com/onsonr/crypto"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
type Signer interface {
|
||||
Sign(msg []byte) ([]byte, error)
|
||||
Verify(msg []byte, sig []byte) error
|
||||
PublicKey() []byte
|
||||
}
|
||||
|
||||
type signer struct {
|
||||
user *types.Keyshare
|
||||
val *types.Keyshare
|
||||
}
|
||||
|
||||
func (k signer) Sign(msg []byte) ([]byte, error) {
|
||||
valSignFunc, err := crypto.GetSignFunc(k.val, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
usrSignFunc, err := crypto.GetSignFunc(k.user, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sig, err := crypto.RunMPCSign(valSignFunc, usrSignFunc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return crypto.SerializeMPCSignature(sig)
|
||||
}
|
||||
|
||||
func (k signer) Verify(msg []byte, sig []byte) error {
|
||||
sigMpc, err := crypto.DeserializeMPCSignature(sig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pk, err := crypto.GetECDSAPublicKey(k.val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ok := crypto.VerifyMPCSignature(sigMpc, msg, pk)
|
||||
if !ok {
|
||||
return types.ErrInvalidSignature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k signer) PublicKey() []byte {
|
||||
if k.user != nil {
|
||||
return k.user.PublicKey
|
||||
}
|
||||
if k.val != nil {
|
||||
return k.val.PublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -4,8 +4,63 @@ import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
)
|
||||
|
||||
// Credential contains all needed information about a WebAuthn credential for storage.
|
||||
type Credential struct {
|
||||
Subject string `json:"handle"`
|
||||
AttestationType string `json:"attestationType"`
|
||||
Origin string `json:"origin"`
|
||||
CredentialID []byte `json:"id"`
|
||||
PublicKey []byte `json:"publicKey"`
|
||||
Transport []string `json:"transport"`
|
||||
SignCount uint32 `json:"signCount"`
|
||||
UserPresent bool `json:"userPresent"`
|
||||
UserVerified bool `json:"userVerified"`
|
||||
BackupEligible bool `json:"backupEligible"`
|
||||
BackupState bool `json:"backupState"`
|
||||
CloneWarning bool `json:"cloneWarning"`
|
||||
}
|
||||
|
||||
// NewCredential will return a credential pointer on successful validation of a registration response.
|
||||
func NewCredential(c *protocol.ParsedCredentialCreationData, origin, handle string) *Credential {
|
||||
return &Credential{
|
||||
Subject: handle,
|
||||
Origin: origin,
|
||||
AttestationType: c.Response.AttestationObject.Format,
|
||||
CredentialID: c.Response.AttestationObject.AuthData.AttData.CredentialID,
|
||||
PublicKey: c.Response.AttestationObject.AuthData.AttData.CredentialPublicKey,
|
||||
Transport: NormalizeTransports(c.Response.Transports),
|
||||
SignCount: c.Response.AttestationObject.AuthData.Counter,
|
||||
UserPresent: c.Response.AttestationObject.AuthData.Flags.HasUserPresent(),
|
||||
UserVerified: c.Response.AttestationObject.AuthData.Flags.HasUserVerified(),
|
||||
BackupEligible: c.Response.AttestationObject.AuthData.Flags.HasBackupEligible(),
|
||||
BackupState: c.Response.AttestationObject.AuthData.Flags.HasAttestedCredentialData(),
|
||||
}
|
||||
}
|
||||
|
||||
// Descriptor converts a Credential into a protocol.CredentialDescriptor.
|
||||
func (c *Credential) Descriptor() protocol.CredentialDescriptor {
|
||||
return protocol.CredentialDescriptor{
|
||||
Type: protocol.PublicKeyCredentialType,
|
||||
CredentialID: c.CredentialID,
|
||||
Transport: ModuleTransportsToProtocol(c.Transport),
|
||||
AttestationType: c.AttestationType,
|
||||
}
|
||||
}
|
||||
|
||||
// This is a signal that the authenticator may be cloned, see CloneWarning above for more information.
|
||||
func (a *Credential) UpdateCounter(authDataCount uint32) {
|
||||
if authDataCount <= a.SignCount && (authDataCount != 0 || a.SignCount != 0) {
|
||||
a.CloneWarning = true
|
||||
return
|
||||
}
|
||||
|
||||
a.SignCount = authDataCount
|
||||
}
|
||||
|
||||
type CredentialDescriptor struct {
|
||||
// The valid credential types.
|
||||
Type CredentialType `json:"type"`
|
||||
|
||||
Reference in New Issue
Block a user