Allow users of password auth to create identity proofs

This commit is contained in:
silverpill 2022-08-15 20:11:58 +00:00
parent a80c11b99c
commit 5f24af4dbf
4 changed files with 39 additions and 12 deletions

View file

@ -101,6 +101,14 @@ paths:
/api/v1/accounts/identity_proof: /api/v1/accounts/identity_proof:
get: get:
summary: Get unsigned data for identity proof. summary: Get unsigned data for identity proof.
parameters:
- name: did
in: query
description: Identifier (DID)
required: true
schema:
type: string
example: 'did:pkh:eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a'
responses: responses:
200: 200:
description: Successful operation description: Successful operation
@ -113,8 +121,8 @@ paths:
description: Identity claim serialized as compact JSON. description: Identity claim serialized as compact JSON.
type: string type: string
example: '{"id":"https://example.com/users/1","ownerOf":"did:pkh:eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a"}' example: '{"id":"https://example.com/users/1","ownerOf":"did:pkh:eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a"}'
403: 400:
description: User's wallet address is not known description: Invalid request parameters
post: post:
summary: Submit identity proof. summary: Submit identity proof.
requestBody: requestBody:
@ -123,6 +131,10 @@ paths:
schema: schema:
type: object type: object
properties: properties:
did:
description: Identifier (DID)
type: string
example: 'did:pkh:eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a'
signature: signature:
description: Signature value. description: Signature value.
type: string type: string
@ -135,9 +147,7 @@ paths:
schema: schema:
$ref: '#/components/schemas/Account' $ref: '#/components/schemas/Account'
400: 400:
description: Invalid signature. description: Invalid proof data.
403:
description: User's wallet address is not known
/api/v1/accounts/authorize_subscription: /api/v1/accounts/authorize_subscription:
get: get:
summary: Get authorization for setting up paid subscription. summary: Get authorization for setting up paid subscription.

View file

@ -235,6 +235,11 @@ impl AccountUpdateData {
} }
} }
#[derive(Deserialize)]
pub struct IdentityClaimQueryParams {
pub did: String,
}
#[derive(Serialize)] #[derive(Serialize)]
pub struct IdentityClaim { pub struct IdentityClaim {
pub claim: String, pub claim: String,
@ -242,6 +247,7 @@ pub struct IdentityClaim {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct IdentityProofData { pub struct IdentityProofData {
pub did: String,
pub signature: String, pub signature: String,
} }

View file

@ -72,6 +72,7 @@ use super::types::{
FollowData, FollowData,
FollowListQueryParams, FollowListQueryParams,
IdentityClaim, IdentityClaim,
IdentityClaimQueryParams,
IdentityProofData, IdentityProofData,
RelationshipQueryParams, RelationshipQueryParams,
SearchDidQueryParams, SearchDidQueryParams,
@ -224,13 +225,13 @@ async fn get_identity_claim(
auth: BearerAuth, auth: BearerAuth,
config: web::Data<Config>, config: web::Data<Config>,
db_pool: web::Data<Pool>, db_pool: web::Data<Pool>,
query_params: web::Query<IdentityClaimQueryParams>,
) -> Result<HttpResponse, HttpError> { ) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?; let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?; let current_user = get_current_user(db_client, auth.token()).await?;
let actor_id = current_user.profile.actor_id(&config.instance_url()); let actor_id = current_user.profile.actor_id(&config.instance_url());
let wallet_address = current_user.wallet_address.as_ref() let did = query_params.did.parse::<DidPkh>()
.ok_or(HttpError::PermissionError)?; .map_err(|_| ValidationError("invalid DID"))?;
let did = DidPkh::from_address(&config.default_currency(), wallet_address);
let claim = create_identity_claim(&actor_id, &did) let claim = create_identity_claim(&actor_id, &did)
.map_err(|_| HttpError::InternalError)?; .map_err(|_| HttpError::InternalError)?;
let response = IdentityClaim { claim }; let response = IdentityClaim { claim };
@ -247,9 +248,18 @@ async fn create_identity_proof(
let db_client = &**get_database_client(&db_pool).await?; let db_client = &**get_database_client(&db_pool).await?;
let mut current_user = get_current_user(db_client, auth.token()).await?; let mut current_user = get_current_user(db_client, auth.token()).await?;
let actor_id = current_user.profile.actor_id(&config.instance_url()); let actor_id = current_user.profile.actor_id(&config.instance_url());
let wallet_address = current_user.wallet_address.as_ref() let did = proof_data.did.parse::<DidPkh>()
.ok_or(HttpError::PermissionError)?; .map_err(|_| ValidationError("invalid DID"))?;
let did = DidPkh::from_address(&config.default_currency(), wallet_address); if did.currency() != Some(config.default_currency()) {
return Err(ValidationError("unsupported chain ID").into());
};
let maybe_public_address =
current_user.public_wallet_address(&config.default_currency());
if let Some(address) = maybe_public_address {
if did.address != address {
return Err(ValidationError("DID doesn't match current identity").into());
};
};
verify_identity_proof( verify_identity_proof(
&actor_id, &actor_id,
&did, &did,

View file

@ -48,7 +48,8 @@ impl User {
/// Returns wallet address if it is verified /// Returns wallet address if it is verified
pub fn public_wallet_address(&self, currency: &Currency) -> Option<String> { pub fn public_wallet_address(&self, currency: &Currency) -> Option<String> {
for proof in self.profile.identity_proofs.clone().into_inner() { for proof in self.profile.identity_proofs.clone().into_inner() {
// Return first match (it's safe if user is local) // Return the first matching address, because only
// one proof per currency is allowed.
if let Some(ref address_currency) = proof.issuer.currency() { if let Some(ref address_currency) = proof.issuer.currency() {
if address_currency == currency { if address_currency == currency {
return Some(proof.issuer.address); return Some(proof.issuer.address);