From 5410f7bf69026e064379c045de335f9f06ebb60a Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Thu, 29 Aug 2019 17:59:26 +0100 Subject: [PATCH 1/8] Have the in-built identity server support v2 --- lib/SyTest/Identity/Server.pm | 482 +++++++++++++++-------- tests/12login/01threepid-and-password.pl | 8 +- tests/30rooms/12thirdpartyinvite.pl | 29 +- tests/54identity.pl | 24 +- 4 files changed, 355 insertions(+), 188 deletions(-) diff --git a/lib/SyTest/Identity/Server.pm b/lib/SyTest/Identity/Server.pm index 05f9950ef..08ee3b96a 100644 --- a/lib/SyTest/Identity/Server.pm +++ b/lib/SyTest/Identity/Server.pm @@ -17,6 +17,8 @@ my $crypto_sign = Crypt::NaCl::Sodium->sign; my $next_token = 0; +my $id_access_token = "testing"; + sub _init { my $self = shift; @@ -62,223 +64,366 @@ sub on_request my $path = $req->path; my %resp; + my $key_name; - if( $path eq "/_matrix/identity/api/v1/pubkey/isvalid" ) { - my $is_valid = any { $_ eq $req->query_param("public_key") } values %{ $self->{keys} }; - $resp{valid} = $is_valid ? JSON::true : JSON::false; - $req->respond_json( \%resp ); + if( + $path eq "/_matrix/identity/api/v1/pubkey/isvalid" or + $path eq "/_matrix/identity/v2/pubkey/isvalid" + ) { + is_valid( $self, $req ); } - elsif( my ( $key_name ) = $path =~ m#^/_matrix/identity/api/v1/pubkey/([^/]*)$# ) { - if( defined $self->{keys}->{$key_name} ) { - $resp{public_key} = $self->{keys}{$key_name}; - } - $req->respond_json( \%resp ); + elsif( ( $key_name ) = $path =~ m#^/_matrix/identity/api/v1/pubkey/([^/]*)$# ) { + pubkey( $self, $req, $key_name ); + } + elsif( ( $key_name ) = $path =~ m#^/_matrix/identity/v2/pubkey/([^/]*)$# ) { + check_v2( $req ); + pubkey( $self, $req, $key_name ); } elsif( $path eq "/_matrix/identity/api/v1/lookup" ) { - my ( $req ) = @_; - my $medium = $req->query_param( "medium" ); - my $address = $req->query_param( "address" ); - if ( !defined $medium or !defined $address ) { - $req->respond( HTTP::Response->new( 400, "Bad Request", [ Content_Length => 0 ] ) ); - return; - } - my $mxid = $self->{bindings}{ join "\0", $medium, $address }; - if ( "email" eq $medium and defined $mxid ) { - $resp{medium} = $medium; - $resp{address} = $address; - $resp{mxid} = $mxid; - - sign_json( \%resp, - secret_key => $self->{private_key}, - origin => $self->name, - key_id => "ed25519:0", - ); - } - $req->respond_json( \%resp ); + v1_lookup( $self, $req ); + } + elsif( $path eq "/_matrix/identity/v2/lookup" ) { + check_v2( $req ); + v2_lookup( $self, $req ); } elsif( $path eq "/_matrix/identity/v2/hash_details" ) { - $resp{lookup_pepper} = $self->{lookup_pepper}; - @resp{algorithms} = [ "none", "sha256" ]; - $req->respond_json( \%resp ); + check_v2( $req ); + hash_details( $self, $req ); } - elsif( $path eq "/_matrix/identity/v2/lookup" ) { - my ( $req ) = @_; + elsif( $path eq "/_matrix/identity/api/v1/store-invite" ) { + store_invite( $self, $req ); + } + elsif( $path eq "/_matrix/identity/v2/store-invite" ) { + check_v2( $req ); + store_invite( $self, $req ); + } + elsif( $path eq "/_matrix/identity/api/v1/3pid/getValidated3pid" ) { + get_validated_3pid( $self, $req ); + } + elsif( $path eq "/_matrix/identity/v2/3pid/getValidated3pid" ) { + check_v2( $req ); + get_validated_3pid( $self, $req ); + } + elsif ( $path eq "/_matrix/identity/api/v1/3pid/bind" ) { + do_bind( $self, $req ); + } + elsif ( $path eq "/_matrix/identity/v2/3pid/bind" ) { + check_v2( $req ); + do_bind( $self, $req ); + } + elsif ( # v2 /unbind does not require an id_access_token param + $path eq "/_matrix/identity/v2/3pid/unbind" or + $path eq "/_matrix/identity/api/v1/3pid/unbind" + ) { + unbind( $self, $req ); + } + else { + warn "Unexpected request to Identity Service for $path"; + $req->respond( HTTP::Response->new( 404, "Not Found", [ Content_Length => 0 ] ) ); + } +} - # Parse request parameters +sub check_v2 +{ + # Check that either an id_access_token query parameter or JSON body key exists in the req + my ( $req ) = @_; + my %resp; + + if ( + $req->query_param("id_access_token") and + $req->query_param("id_access_token") eq $id_access_token + ) { + # We found it! + return + } + + # Check the JSON body for the token. This isn't required for all endpoints so only try if + # the request has a body + my $found = 0; + eval { + # We use an eval in case this request doesn't have a JSON body my $body = $req->body_from_json; - my $addresses = $body->{addresses}; - my $pepper = $body->{pepper}; - my $algorithm = $body->{algorithm}; - if ( !$addresses or !$pepper or !$algorithm ) { - $req->respond( HTTP::Response->new( 400, "Bad Request", [ Content_Length => 0 ] ) ); - return; + if ( + $body->{id_access_token} and + $body->{id_access_token} eq $id_access_token + ) { + # We found it! + $found = 1; } + }; - if ( "none" eq $algorithm ) { - foreach my $address ( @$addresses ) { - my @address_medium = split ' ', $address; - - # Check the medium and address are in the right format - if ( scalar( @address_medium ) ne 2 ) { - $resp{error} = "Address is not two strings separated by a space: ${address}"; - $resp{errcode} = "M_UNKNOWN"; - $req->respond_json( \%resp, code => 400 ); - return; - } + # Couldn't find an access token + if ( !$found ) { + $resp{error} = "Missing id_access_token parameter"; + $resp{errcode} = "M_MISSING_PARAM"; + $req->respond_json( \%resp, code => 400 ); + } +} - # Parse the medium and address from the string - my $user_address = $address_medium[0]; - my $user_medium = $address_medium[1]; +sub is_valid +{ + my $self = shift; + my ( $req ) = @_; + my %resp; - # Extract the MXID for this address/medium combo from the bindings hash - # We need to swap around medium and address here as it's stored $medium, $address - # locally, not $address, $medium - my $mxid = $self->{bindings}{ join "\0", $user_medium, $user_address }; + my $valid = any { $_ eq $req->query_param("public_key") } values %{ $self->{keys} }; + $resp{valid} = $valid ? JSON::true : JSON::false; + $req->respond_json( \%resp ); +} - $resp{mappings}{$address} = $mxid; - } +sub validate_identity +{ + my $self = shift; + my ( $medium, $address, $client_secret ) = @_; - # Return the mappings - $req->respond_json( \%resp ); - } - elsif ( "sha256" eq $algorithm ) { - # Check that the user provided the correct pepper - if ( $self->{lookup_pepper} ne $pepper ) { - # Return an error message - $resp{error} = "Incorrect value for lookup_pepper"; - $resp{errcode} = "M_INVALID_PEPPER"; - $resp{algorithm} = "sha256"; - $resp{lookup_pepper} = $self->{lookup_pepper}; + my $sid = "session_${\ $self->{sid}++ }"; - $req->respond_json( \%resp, code => 400 ); - return; - } + $self->{validated}{$sid} = { + medium => $medium, + address => $address, + }; - # Attempt to find the hash of each entry and return the corresponding mxid - foreach my $hash ( @$addresses ) { - $resp{mappings}{$hash} = $self->{hashes}{$hash}; - } + return $sid; +} - $req->respond_json( \%resp ); - } - else { - # Unknown algorithm provided - $resp{error} = "Unknown algorithm"; - $resp{errcode} = "M_INVALID_PARAM"; +sub pubkey +{ + my $self = shift; + my ( $req, $key_name ) = @_; + my %resp; - $req->respond_json( \%resp, code => 400 ); - } + if( defined $self->{keys}{$key_name} ) { + $resp{public_key} = $self->{keys}{$key_name}; } - elsif( $path eq "/_matrix/identity/api/v1/store-invite" ) { - my $body = $req->body_from_json; - my $medium = $body->{medium}; - my $address = $body->{address}; - my $sender = $body->{sender}; - my $room_id = $body->{room_id}; - unless( ( defined $body->{medium} and defined $address and defined $sender and defined $room_id ) ) { - $req->respond( HTTP::Response->new( 400, "Bad Request", [ Content_Length => 0 ] ) ); - return; - } - my $token = "".$next_token++; - my $key = join "\0", $medium, $address; - push @{ $self->{invites}->{$key} }, { - address => $address, - medium => $medium, - room_id => $room_id, - sender => $sender, - token => $token, - guest_access_token => $body->{guest_access_token}, - }; - $resp{token} = $token; - $resp{display_name} = "Bob"; - $resp{public_key} = $self->{keys}{"ed25519:0"}; - - my $key_validity_url = "https://" . $self->name . "/_matrix/identity/api/v1/pubkey/isvalid"; - - $resp{public_keys} = [ - { - public_key => $self->{keys}{"ed25519:0"}, - key_validity_url => $key_validity_url, - }, - { - public_key => $self->{keys}{"ed25519:ephemeral"}, - key_validity_url => $key_validity_url, - }, - ]; - $req->respond_json( \%resp ); - } - elsif( $path eq "/_matrix/identity/api/v1/3pid/getValidated3pid" ) { - my $sid = $req->query_param( "sid" ); - unless( defined $sid and defined $self->{validated}{$sid} ) { - $req->respond( HTTP::Response->new( 400, "Bad Request", [ Content_Length => 0 ] ) ); - return; - } - $resp{medium} = $self->{validated}{$sid}{medium}; - $resp{address} = $self->{validated}{$sid}{address}; - $resp{validated_at} = 0; - $req->respond_json( \%resp ); - } - elsif ( $path eq "/_matrix/identity/api/v1/3pid/bind" ) { - my $body = $req->body_from_json; - my $sid = $body->{sid}; - my $mxid = $body->{mxid}; - - my $medium = $self->{validated}{$sid}{medium}; - my $address = $self->{validated}{$sid}{address}; + $req->respond_json( \%resp ); +} - $self->bind_identity( undef, $medium, $address, $mxid ); +sub v1_lookup +{ + my $self = shift; + my ( $req ) = @_; + my %resp; + my $medium = $req->query_param( "medium" ); + my $address = $req->query_param( "address" ); + if ( !defined $medium or !defined $address ) { + $req->respond( HTTP::Response->new( 400, "Bad Request", [ Content_Length => 0 ] ) ); + return; + } + my $mxid = $self->{bindings}{ join "\0", $medium, $address }; + if ( "email" eq $medium and defined $mxid ) { $resp{medium} = $medium; $resp{address} = $address; $resp{mxid} = $mxid; - $resp{not_before} = 0; - $resp{not_after} = 4582425849161; - $resp{ts} = 0; sign_json( \%resp, secret_key => $self->{private_key}, origin => $self->name, key_id => "ed25519:0", ); + } + $req->respond_json( \%resp ); +} - $req->respond_json( \%resp ); +sub hash_details +{ + my $self = shift; + my ( $req ) = @_; + my %resp; + + $resp{lookup_pepper} = $self->{lookup_pepper}; + @resp{algorithms} = [ "none", "sha256" ]; + $req->respond_json( \%resp ); +} + +sub v2_lookup +{ + my $self = shift; + my ( $req ) = @_; + my %resp; + + # Parse request parameters + my $body = $req->body_from_json; + my $addresses = $body->{addresses}; + my $pepper = $body->{pepper}; + my $algorithm = $body->{algorithm}; + if ( !$addresses or !$pepper or !$algorithm ) { + $req->respond( HTTP::Response->new( 400, "Bad Request", [ Content_Length => 0 ] ) ); + return; } - elsif ( $path eq "/_matrix/identity/api/v1/3pid/unbind" ) { - my $body = $req->body_from_json; - my $mxid = $body->{mxid}; - my $medium = $body->{threepid}{medium}; - my $address = $body->{threepid}{address}; + if ( "none" eq $algorithm ) { + foreach my $address ( @$addresses ) { + my @address_medium = split ' ', $address; + + # Check the medium and address are in the right format + if ( scalar( @address_medium ) ne 2 ) { + $resp{error} = "Address is not two strings separated by a space: ${address}"; + $resp{errcode} = "M_UNKNOWN"; - unless ($self->{bindings}{ join "\0", $medium, $address } eq $mxid ) { - $req->respond( HTTP::Response->new( 404, "Not Found", [ Content_Length => 0 ] ) ); + $req->respond_json( \%resp, code => 400 ); + return; + } + + # Parse the medium and address from the string + my $user_address = $address_medium[0]; + my $user_medium = $address_medium[1]; + + # Extract the MXID for this address/medium combo from the bindings hash + # We need to swap around medium and address here as it's stored $medium, $address + # locally, not $address, $medium + my $mxid = $self->{bindings}{ join "\0", $user_medium, $user_address }; + + $resp{mappings}{$address} = $mxid; + } + + # Return the mappings + $req->respond_json( \%resp ); + } + elsif ( "sha256" eq $algorithm ) { + # Check that the user provided the correct pepper + if ( $self->{lookup_pepper} ne $pepper ) { + # Return an error message + $resp{error} = "Incorrect value for lookup_pepper"; + $resp{errcode} = "M_INVALID_PEPPER"; + $resp{algorithm} = "sha256"; + $resp{lookup_pepper} = $self->{lookup_pepper}; + + $req->respond_json( \%resp, code => 400 ); return; } - delete($self->{bindings}{ join "\0", $medium, $address }); + # Attempt to find the hash of each entry and return the corresponding mxid + foreach my $hash ( @$addresses ) { + $resp{mappings}{$hash} = $self->{hashes}{$hash}; + } $req->respond_json( \%resp ); } else { - warn "Unexpected request to Identity Service for $path"; - $req->respond( HTTP::Response->new( 404, "Not Found", [ Content_Length => 0 ] ) ); + # Unknown algorithm provided + $resp{error} = "Unknown algorithm"; + $resp{errcode} = "M_INVALID_PARAM"; + + $req->respond_json( \%resp, code => 400 ); } } -sub validate_identity +sub store_invite { my $self = shift; - my ( $medium, $address, $client_secret ) = @_; - - my $sid = "session_${\ $self->{sid}++ }"; + my ( $req ) = @_; + my %resp; - $self->{validated}{$sid} = { - medium => $medium, - address => $address, + my $body = $req->body_from_json; + my $medium = $body->{medium}; + my $address = $body->{address}; + my $sender = $body->{sender}; + my $room_id = $body->{room_id}; + unless( ( defined $body->{medium} and defined $address and defined $sender and defined $room_id ) ) { + $req->respond( HTTP::Response->new( 400, "Bad Request", [ Content_Length => 0 ] ) ); + return; + } + my $token = "".$next_token++; + my $key = join "\0", $medium, $address; + push @{ $self->{invites}->{$key} }, { + address => $address, + medium => $medium, + room_id => $room_id, + sender => $sender, + token => $token, + guest_access_token => $body->{guest_access_token}, }; + $resp{token} = $token; + $resp{display_name} = "Bob"; + $resp{public_key} = $self->{keys}{"ed25519:0"}; + + my $key_validity_url = "https://" . $self->name . "/_matrix/identity/v2/pubkey/isvalid"; + + $resp{public_keys} = [ + { + public_key => $self->{keys}{"ed25519:0"}, + key_validity_url => $key_validity_url, + }, + { + public_key => $self->{keys}{"ed25519:ephemeral"}, + key_validity_url => $key_validity_url, + }, + ]; + + $req->respond_json( \%resp ); +} - return $sid; +sub get_validated_3pid +{ + my $self = shift; + my ( $req ) = @_; + my %resp; + + my $sid = $req->query_param( "sid" ); + unless( defined $sid and defined $self->{validated}{$sid} ) { + $req->respond( HTTP::Response->new( 400, "Bad Request", [ Content_Length => 0 ] ) ); + return; + } + $resp{medium} = $self->{validated}{$sid}{medium}; + $resp{address} = $self->{validated}{$sid}{address}; + $resp{validated_at} = 0; + $req->respond_json( \%resp ); +} + +# bind is a reserved method name +sub do_bind +{ + my $self = shift; + my ( $req ) = @_; + my %resp; + + my $body = $req->body_from_json; + my $sid = $body->{sid}; + my $mxid = $body->{mxid}; + + my $medium = $self->{validated}{$sid}{medium}; + my $address = $self->{validated}{$sid}{address}; + + $self->bind_identity( undef, $medium, $address, $mxid ); + + $resp{medium} = $medium; + $resp{address} = $address; + $resp{mxid} = $mxid; + $resp{not_before} = 0; + $resp{not_after} = 4582425849161; + $resp{ts} = 0; + + sign_json( \%resp, + secret_key => $self->{private_key}, + origin => $self->name, + key_id => "ed25519:0", + ); + + $req->respond_json( \%resp ); +} + +sub unbind +{ + my $self = shift; + my ( $req ) = @_; + my %resp; + + my $body = $req->body_from_json; + my $mxid = $body->{mxid}; + + my $medium = $body->{threepid}{medium}; + my $address = $body->{threepid}{address}; + + unless ($self->{bindings}{ join "\0", $medium, $address } eq $mxid ) { + $req->respond( HTTP::Response->new( 404, "Not Found", [ Content_Length => 0 ] ) ); + return; + } + + delete($self->{bindings}{ join "\0", $medium, $address }); + + $req->respond_json( \%resp ); } sub bind_identity @@ -373,6 +518,11 @@ sub invites_for return $self->{invites}{ join "\0", $medium, $address }; } +sub get_access_token +{ + return $id_access_token; +} + sub name { my $self = shift; diff --git a/tests/12login/01threepid-and-password.pl b/tests/12login/01threepid-and-password.pl index 9b3a9a58b..b5313e026 100644 --- a/tests/12login/01threepid-and-password.pl +++ b/tests/12login/01threepid-and-password.pl @@ -12,6 +12,7 @@ my $medium = "email"; my $address = 'bob@example.com'; my $client_secret = "a client secret"; + my $id_access_token = $id_server->get_access_token(); my $sid = $id_server->validate_identity( $medium, $address, $client_secret ); @@ -20,9 +21,10 @@ uri => "/r0/account/3pid", content => { three_pid_creds => { - id_server => $id_server->name, - sid => $sid, - client_secret => $client_secret, + id_server => $id_server->name, + id_access_token => $id_access_token, + sid => $sid, + client_secret => $client_secret, }, bind => JSON::false, }, diff --git a/tests/30rooms/12thirdpartyinvite.pl b/tests/30rooms/12thirdpartyinvite.pl index 421a5c7cb..6b6fbf44d 100644 --- a/tests/30rooms/12thirdpartyinvite.pl +++ b/tests/30rooms/12thirdpartyinvite.pl @@ -11,6 +11,7 @@ my $invitee_mxid = $invitee->user_id; my $room_id; + my $id_access_token = $id_server->get_access_token(); $id_server->bind_identity( undef, "email", $invitee_email, $invitee ) ->then( sub { @@ -23,9 +24,10 @@ uri => "/r0/rooms/$room_id/invite", content => { - id_server => $id_server->name, - medium => "email", - address => $invitee_email, + id_server => $id_server->name, + id_access_token => $id_access_token, + medium => "email", + address => $invitee_email, }, ); })->then( sub { @@ -51,6 +53,7 @@ my $invitee_mxid = $invitee->user_id; my $room_id; + my $id_access_token = $id_server->get_access_token(); $id_server->bind_identity( undef, "email", $invitee_email, $invitee ) ->then( sub { @@ -63,9 +66,10 @@ uri => "/r0/rooms/$room_id/invite", content => { - id_server => $id_server->name, - medium => "email", - address => $invitee_email, + id_server => $id_server->name, + id_access_token => $id_access_token, + medium => "email", + address => $invitee_email, }, ); })->then( sub { @@ -91,6 +95,7 @@ my $invitee_mxid = $invitee->user_id; my $room_id; + my $id_access_token = $id_server->get_access_token(); $id_server->bind_identity( undef, "email", $invitee_email, $invitee ) ->then( sub { @@ -98,6 +103,7 @@ medium => "email", address => $invitee_email, id_server => $id_server->name, + id_access_token => $id_access_token, }; matrix_create_room( $inviter, invite_3pid => [ $invite_info ] ); })->then( sub { @@ -255,7 +261,7 @@ sub can_invite_unbound_3pid return unless $event->{type} eq "m.room.member"; return unless $event->{state_key} eq $invitee->user_id; - assert_eq( $event->{content}{membership}, "invite" ); + assert_eq( $event->{content}{membership}, "invite" ); return 1; }) @@ -464,13 +470,16 @@ sub assert_membership { sub do_3pid_invite { my ( $inviter, $room_id, $id_server, $invitee_email ) = @_; + my $id_access_token = $id_server->get_access_token(); + do_request_json_for( $inviter, method => "POST", uri => "/r0/rooms/$room_id/invite", content => { - id_server => $id_server, - medium => "email", - address => $invitee_email, + id_server => $id_server, + id_access_token => $id_access_token, + medium => "email", + address => $invitee_email, } )->then( sub { my ( $result ) = @_; diff --git a/tests/54identity.pl b/tests/54identity.pl index cafaadb6e..efc8c9166 100644 --- a/tests/54identity.pl +++ b/tests/54identity.pl @@ -7,6 +7,7 @@ my $medium = "email"; my $address = 'bob@example.com'; my $client_secret = "a client secret"; + my $id_access_token = $id_server->get_access_token(); my $sid = $id_server->validate_identity( $medium, $address, $client_secret ); @@ -15,9 +16,10 @@ uri => "/r0/account/3pid", content => { three_pid_creds => { - id_server => $id_server->name, - sid => $sid, - client_secret => $client_secret, + id_server => $id_server->name, + id_access_token => $id_access_token, + sid => $sid, + client_secret => $client_secret, }, bind => JSON::true, }, @@ -40,6 +42,7 @@ my $medium = "email"; my $address = 'bob@example.com'; my $client_secret = "a client secret"; + my $id_access_token = $id_server->get_access_token(); my $sid = $id_server->validate_identity( $medium, $address, $client_secret ); @@ -48,9 +51,10 @@ uri => "/r0/account/3pid", content => { three_pid_creds => { - id_server => $id_server->name, - sid => $sid, - client_secret => $client_secret, + id_server => $id_server->name, + id_access_token => $id_access_token, + sid => $sid, + client_secret => $client_secret, }, bind => JSON::true, }, @@ -115,6 +119,7 @@ my $medium = "email"; my $address = 'bob@example.com'; my $client_secret = "a client secret"; + my $id_access_token = $id_server->get_access_token(); my $sid = $id_server->validate_identity( $medium, $address, $client_secret ); @@ -123,9 +128,10 @@ uri => "/r0/account/3pid", content => { three_pid_creds => { - id_server => $id_server->name, - sid => $sid, - client_secret => $client_secret, + id_server => $id_server->name, + id_access_token => $id_access_token, + sid => $sid, + client_secret => $client_secret, }, bind => JSON::true, }, From ab3ffbdfda58defe156a004bdcb424ea0d2697e7 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Tue, 3 Sep 2019 17:42:21 +0100 Subject: [PATCH 2/8] Fix call to get_access_token --- tests/30rooms/12thirdpartyinvite.pl | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/tests/30rooms/12thirdpartyinvite.pl b/tests/30rooms/12thirdpartyinvite.pl index 6b6fbf44d..201e52fb0 100644 --- a/tests/30rooms/12thirdpartyinvite.pl +++ b/tests/30rooms/12thirdpartyinvite.pl @@ -189,7 +189,7 @@ sub can_invite_unbound_3pid { my ( $room_id, $inviter, $invitee, $hs_uribase, $id_server ) = @_; - do_3pid_invite( $inviter, $room_id, $id_server->name, $invitee_email ) + do_3pid_invite( $inviter, $room_id, $id_server, $invitee_email ) ->then( sub { $id_server->bind_identity( $hs_uribase, "email", $invitee_email, $invitee ); })->then( sub { @@ -245,7 +245,7 @@ sub can_invite_unbound_3pid ->then( sub { ( $room_id ) = @_; - do_3pid_invite( $inviter, $room_id, $id_server->name, $invitee_email ) + do_3pid_invite( $inviter, $room_id, $id_server, $invitee_email ) })->then( sub { await_event_for( $joiner, filter => sub { my ( $event ) = @_; @@ -313,7 +313,7 @@ sub can_invite_unbound_3pid })->then( sub { matrix_join_room( $other_member, $room_id ); })->then( sub { - do_3pid_invite( $inviter, $room_id, $id_server->name, $invitee_email ) + do_3pid_invite( $inviter, $room_id, $id_server, $invitee_email ) })->then( sub { matrix_leave_room( $inviter, $room_id ); })->then( sub { @@ -342,7 +342,7 @@ sub can_invite_unbound_3pid ->then( sub { ( $room_id ) = @_; - do_3pid_invite( $inviter, $room_id, $id_server->name, $invitee_email ) + do_3pid_invite( $inviter, $room_id, $id_server, $invitee_email ) })->then( sub { matrix_get_room_state( $inviter, $room_id, ) })->then( sub { @@ -433,7 +433,7 @@ sub invite_should_fail { ->then( sub { ( $room_id ) = @_; log_if_fail "Created room id $room_id"; - do_3pid_invite( $inviter, $room_id, $id_server->name, $invitee_email ) + do_3pid_invite( $inviter, $room_id, $id_server, $invitee_email ) })->then( sub { $bind_sub->( $id_server ); })->then( sub { @@ -470,14 +470,12 @@ sub assert_membership { sub do_3pid_invite { my ( $inviter, $room_id, $id_server, $invitee_email ) = @_; - my $id_access_token = $id_server->get_access_token(); - do_request_json_for( $inviter, method => "POST", uri => "/r0/rooms/$room_id/invite", content => { - id_server => $id_server, - id_access_token => $id_access_token, + id_server => $id_server->name, + id_access_token => $id_server->get_access_token(), medium => "email", address => $invitee_email, } From 9f76cd6575e4552707439334e5da9fc374d323ee Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Thu, 5 Sep 2019 12:02:33 +0100 Subject: [PATCH 3/8] Address review comments and PoD docstrings --- lib/SyTest/Identity/Server.pm | 331 +++++++++++++++++++++++++++------- 1 file changed, 266 insertions(+), 65 deletions(-) diff --git a/lib/SyTest/Identity/Server.pm b/lib/SyTest/Identity/Server.pm index 08ee3b96a..c6ea10158 100644 --- a/lib/SyTest/Identity/Server.pm +++ b/lib/SyTest/Identity/Server.pm @@ -17,7 +17,10 @@ my $crypto_sign = Crypt::NaCl::Sodium->sign; my $next_token = 0; -my $id_access_token = "testing"; +# Perpetually correct access token for authenticating with v2 Identity Service API endpoints. +# v2 endpoint calls to this identity server should include this value for their +# `id_access_token` parameter +my $ID_ACCESS_TOKEN = "swordfish"; sub _init { @@ -44,6 +47,14 @@ sub _init return $self->SUPER::_init( @_ ); } +=head2 + + $self->rotate_keys(); + +Creates new ed25519 public/private key pairs for this server. + +=cut + sub rotate_keys { my $self = shift; @@ -57,65 +68,64 @@ sub rotate_keys }; } +=head2 + +Handles incoming HTTP requests to this server. + +=cut + sub on_request { my $self = shift; my ( $req ) = @_; my $path = $req->path; - my %resp; my $key_name; if( $path eq "/_matrix/identity/api/v1/pubkey/isvalid" or $path eq "/_matrix/identity/v2/pubkey/isvalid" ) { - is_valid( $self, $req ); + $self->on_is_valid( $req ); } elsif( ( $key_name ) = $path =~ m#^/_matrix/identity/api/v1/pubkey/([^/]*)$# ) { - pubkey( $self, $req, $key_name ); + $self->on_pubkey( $req, $key_name ); } elsif( ( $key_name ) = $path =~ m#^/_matrix/identity/v2/pubkey/([^/]*)$# ) { - check_v2( $req ); - pubkey( $self, $req, $key_name ); + $self->check_v2( $req ) and $self->on_pubkey( $req, $key_name ); } elsif( $path eq "/_matrix/identity/api/v1/lookup" ) { - v1_lookup( $self, $req ); + $self->on_v1_lookup( $req ); } elsif( $path eq "/_matrix/identity/v2/lookup" ) { - check_v2( $req ); - v2_lookup( $self, $req ); + $self->check_v2( $req ) and $self->on_v2_lookup( $req ); } elsif( $path eq "/_matrix/identity/v2/hash_details" ) { - check_v2( $req ); - hash_details( $self, $req ); + $self->check_v2( $req ) and $self->on_hash_details( $req ); } elsif( $path eq "/_matrix/identity/api/v1/store-invite" ) { - store_invite( $self, $req ); + $self->on_store_invite( $req ); } elsif( $path eq "/_matrix/identity/v2/store-invite" ) { - check_v2( $req ); - store_invite( $self, $req ); + $self->check_v2( $req ) and $self->on_store_invite( $req ); } elsif( $path eq "/_matrix/identity/api/v1/3pid/getValidated3pid" ) { - get_validated_3pid( $self, $req ); + $self->on_get_validated_3pid( $req ); } elsif( $path eq "/_matrix/identity/v2/3pid/getValidated3pid" ) { - check_v2( $req ); - get_validated_3pid( $self, $req ); + $self->check_v2( $req ) and $self->on_get_validated_3pid( $req ); } elsif ( $path eq "/_matrix/identity/api/v1/3pid/bind" ) { - do_bind( $self, $req ); + $self->on_bind( $req ); } elsif ( $path eq "/_matrix/identity/v2/3pid/bind" ) { - check_v2( $req ); - do_bind( $self, $req ); + $self->check_v2( $req ) and $self->on_bind( $req ); } elsif ( # v2 /unbind does not require an id_access_token param $path eq "/_matrix/identity/v2/3pid/unbind" or $path eq "/_matrix/identity/api/v1/3pid/unbind" ) { - unbind( $self, $req ); + $self->on_unbind( $req ); } else { warn "Unexpected request to Identity Service for $path"; @@ -123,45 +133,68 @@ sub on_request } } +=head2 check_v2 + + $self->check_v2 ( $req ) and do_something_else(); + +A helper method that takes an HTTP request and checks if an C parameter +matching C<$ID_ACCESS_TOKEN> is present in either the query parameters or the top-level JSON of +the request body. + +Returns C<0> or C<1> depending on whether a correct C value was found. + +Responds to the HTTP request with an error message if no C value was found. + +=cut + sub check_v2 { # Check that either an id_access_token query parameter or JSON body key exists in the req + my $self = shift; my ( $req ) = @_; my %resp; if ( $req->query_param("id_access_token") and - $req->query_param("id_access_token") eq $id_access_token + $req->query_param("id_access_token") eq $ID_ACCESS_TOKEN ) { # We found it! - return + return 1 } # Check the JSON body for the token. This isn't required for all endpoints so only try if # the request has a body - my $found = 0; - eval { - # We use an eval in case this request doesn't have a JSON body - my $body = $req->body_from_json; - if ( - $body->{id_access_token} and - $body->{id_access_token} eq $id_access_token - ) { - # We found it! - $found = 1; - } - }; + my $body = eval { $req->body_from_json }; + if ( + $body and + $body->{id_access_token} and + $body->{id_access_token} eq $ID_ACCESS_TOKEN + ) { + # We found it! + return 1 + } # Couldn't find an access token - if ( !$found ) { - $resp{error} = "Missing id_access_token parameter"; - $resp{errcode} = "M_MISSING_PARAM"; - $req->respond_json( \%resp, code => 400 ); - } + $resp{error} = "Missing id_access_token parameter"; + $resp{errcode} = "M_MISSING_PARAM"; + $req->respond_json( \%resp, code => 400 ); + return 0 } -sub is_valid +=head2 on_is_valid + + $self->on_is_valid( $req ); + +Given a HTTP request, check that the value of the public_key query parameter matches a key in +the C<$self->{keys}> dictionary. + +Responds to the HTTP request with JSON body C<{"valid": true}> or C<{"valid": false}> depending +on whether a match was found. + +=cut + +sub on_is_valid { my $self = shift; my ( $req ) = @_; @@ -172,22 +205,19 @@ sub is_valid $req->respond_json( \%resp ); } -sub validate_identity -{ - my $self = shift; - my ( $medium, $address, $client_secret ) = @_; +=head2 - my $sid = "session_${\ $self->{sid}++ }"; + $self->on_pubkey( $req, $key_name ); - $self->{validated}{$sid} = { - medium => $medium, - address => $address, - }; +Given a HTTP request and a key name, return the public key corresponding to that key name if +known. - return $sid; -} +Responds to the HTTP request with JSON body C<{"public_key": "some_public_key"}> if a public +key is found, otherwise return an empty body. + +=cut -sub pubkey +sub on_pubkey { my $self = shift; my ( $req, $key_name ) = @_; @@ -199,7 +229,21 @@ sub pubkey $req->respond_json( \%resp ); } -sub v1_lookup +=head2 + + $self->on_v1_lookup( $req ); + +Given a HTTP request containing C and C
query parameters, look up an +address/medium combination in the server. + +If found, this method will respond to the request with a signed JSON object containing the +C, C
and C of the found user. + +If not found, the request will be sent an empty JSON body. + +=cut + +sub on_v1_lookup { my $self = shift; my ( $req ) = @_; @@ -226,7 +270,17 @@ sub v1_lookup $req->respond_json( \%resp ); } -sub hash_details +=head2 + + $self->on_hash_details( $req ); + +Given a HTTP request, this function will respond with a JSON body with a C +string containing the server's lookup pepper, and a C array containing all of the +lookup algorithms the server supports. + +=cut + +sub on_hash_details { my $self = shift; my ( $req ) = @_; @@ -237,7 +291,24 @@ sub hash_details $req->respond_json( \%resp ); } -sub v2_lookup +=head2 + + $self->on_v2_lookup( $req ); + +Given a HTTP request containing C, C and C fields in its JSON +body, perform a v2 lookup. This involves checking the algorithm that was specified, and whether +it matches one the identity server supports. Then depending on the algorithm, a lookup of the +data in the C field is carried out. + +If the request contains an algorithm that the identity server does not support, it will be +responded to with a C<400 M_INVALID_PARAM>. If the request contains a pepper that doesn't match +the server's, it will be responded to with a C<400 M_INVALID_PEPPER>. Otherwise, the request +will be responded to with a JSON body with a C field, which contains the results of +the lookup on the given C. + +=cut + +sub on_v2_lookup { my $self = shift; my ( $req ) = @_; @@ -258,7 +329,7 @@ sub v2_lookup my @address_medium = split ' ', $address; # Check the medium and address are in the right format - if ( scalar( @address_medium ) ne 2 ) { + if ( scalar( @address_medium ) != 2 ) { $resp{error} = "Address is not two strings separated by a space: ${address}"; $resp{errcode} = "M_UNKNOWN"; @@ -267,8 +338,7 @@ sub v2_lookup } # Parse the medium and address from the string - my $user_address = $address_medium[0]; - my $user_medium = $address_medium[1]; + my ( $user_address, $user_medium ) = @address_medium; # Extract the MXID for this address/medium combo from the bindings hash # We need to swap around medium and address here as it's stored $medium, $address @@ -310,7 +380,18 @@ sub v2_lookup } } -sub store_invite +=head2 + + $self->on_store_invite( $req ); + +Given a HTTP request with a JSON body containing C, C
, C and +C keys, create and store an invite containing them. + +Responds to the HTTP request with C, C and public_keys. + +=cut + +sub on_store_invite { my $self = shift; my ( $req ) = @_; @@ -355,7 +436,18 @@ sub store_invite $req->respond_json( \%resp ); } -sub get_validated_3pid +=head2 + + $self->on_get_validated_3pid( $req ); + +Given a HTTP request with a session ID C query parameter, respond with C, +C
and C JSON body fields corresponding to the session ID. + +If the session ID is unknown, respond with a HTTP C<400>. + +=cut + +sub on_get_validated_3pid { my $self = shift; my ( $req ) = @_; @@ -372,8 +464,19 @@ sub get_validated_3pid $req->respond_json( \%resp ); } -# bind is a reserved method name -sub do_bind +=head2 + + $self->on_bind( $req ); + +Given a HTTP request containing session ID C and Matrix ID C JSON body fields, bind +the medium and address corresponding to the session ID to the given Matrix ID. + +Responds to the HTTP request with a signed JSON body containing , C
, C, + C, C and C fields. + +=cut + +sub on_bind { my $self = shift; my ( $req ) = @_; @@ -404,7 +507,18 @@ sub do_bind $req->respond_json( \%resp ); } -sub unbind +=head2 + + $self->on_unbind( $req ); + +Given a HTTP request containing a Matrix ID C, +which itself has C and C
fields, remove the binding from the server. + +If no binding is found, respond to the HTTP request with a C<404 Not Found> error. + +=cut + +sub on_unbind { my $self = shift; my ( $req ) = @_; @@ -426,6 +540,26 @@ sub unbind $req->respond_json( \%resp ); } +=head2 + + $self->bind_identity( $hs_uribase, $medium, $address, $user, $before_resp ); + +Shortcut to creating a new threepid identity binding, and calling the C callback of a +homeserver specified by C. + +Example: + + $self->bind_identity( undef, "email", $invitee_email, $invitee_mxid ); + +Store the C and C
as well as the hash of the address for v2 lookup. Finally, +call the C endpoint of the HS specified by C +(if defined). + +If C<$before_resp> is a function, that function will be executed before the C call is +made. + +=cut + sub bind_identity { my $self = shift; @@ -482,6 +616,20 @@ sub bind_identity ); } +=head2 + + $self->lookup_identity( $medium, $address ); + +Shortcut for finding the MXID that's been previously bound to the C, C
combo. + +Example: + + $self->lookup_identity( "email", "bob@example.com" ); + +Returns the matching Matrix ID, or C if one is not found. + +=cut + sub lookup_identity { my $self = shift; @@ -495,6 +643,25 @@ sub lookup_identity return undef; } +=head2 + + $self->sign( $to_sign, %opts ); + +Sign some data B using the server's private key. Setting C to C<1> will +use the server's ephemeral private key for signing instead. + +Example: + + my %req = ( + mxid => $invitee->user_id, + sender => $inviter->user_id, + token => $token, + ); + + $self->sign( \%req, ephemeral => 1); + +=cut + sub sign { my $self = shift; @@ -510,6 +677,21 @@ sub sign ); } +=head2 + + $self->invites_for( $medium, $address ); + +Retrieve the invites for a C, C
pair. + +Example: + + my $invites = $self->invites_for( "email", "threeheadedmonkey@island.com" ); + +Returns a reference to an array of invites that correspond to the given C, C
+pair. + +=cut + sub invites_for { my $self = shift; @@ -518,11 +700,30 @@ sub invites_for return $self->{invites}{ join "\0", $medium, $address }; } +=head2 + + $self->get_access_token(); + +Returns the access token for this server. Required for making calls to authenticated V2 +Identity Service endpoints. + +Example: + + my $access_token = $self->get_access_token(); + +=cut + sub get_access_token { - return $id_access_token; + return $ID_ACCESS_TOKEN; } +=head2 + + $self->name(): + +Return a string made up of the server's hostname and port, separated by a colon. + sub name { my $self = shift; From 21f0c864c9e99971f60e6dcd12a9ad91d2d5367e Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Fri, 6 Sep 2019 11:30:29 +0100 Subject: [PATCH 4/8] Fix name docstring and re-add validate_identity function --- lib/SyTest/Identity/Server.pm | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lib/SyTest/Identity/Server.pm b/lib/SyTest/Identity/Server.pm index c6ea10158..f185a4a21 100644 --- a/lib/SyTest/Identity/Server.pm +++ b/lib/SyTest/Identity/Server.pm @@ -205,6 +205,33 @@ sub on_is_valid $req->respond_json( \%resp ); } +=head2 + + $self->validate_identity( $medium, $address, $client_secret ); + +Validates a C, C
combo against a given C. + +Example: + + $self->validate_identity( "email", "heyitsfred@example.com", "apples" ); + +Returns the session ID corresponding to the given parameters if one is found. + +=cut + +sub validate_identity +{ + my $self = shift; + my ( $medium, $address, $client_secret ) = @_; + my $sid = "session_${\ $self->{sid}++ }"; + $self->on_pubkey( $req, $key_name ); + $self->{validated}{$sid} = { + medium => $medium, + address => $address, + }; + return $sid; +} + =head2 $self->on_pubkey( $req, $key_name ); @@ -724,6 +751,8 @@ sub get_access_token Return a string made up of the server's hostname and port, separated by a colon. +=cut + sub name { my $self = shift; From 3c9fbcb17ef7322a402197b2557c9ed61975ff7a Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Fri, 6 Sep 2019 11:38:40 +0100 Subject: [PATCH 5/8] fix validate_identity --- lib/SyTest/Identity/Server.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/SyTest/Identity/Server.pm b/lib/SyTest/Identity/Server.pm index f185a4a21..d18a8f9eb 100644 --- a/lib/SyTest/Identity/Server.pm +++ b/lib/SyTest/Identity/Server.pm @@ -223,12 +223,14 @@ sub validate_identity { my $self = shift; my ( $medium, $address, $client_secret ) = @_; + my $sid = "session_${\ $self->{sid}++ }"; - $self->on_pubkey( $req, $key_name ); + $self->{validated}{$sid} = { medium => $medium, address => $address, }; + return $sid; } From aa48908a214d9458c698748cdae851f6c4ea4851 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Mon, 9 Sep 2019 13:01:33 +0100 Subject: [PATCH 6/8] Address review comments --- lib/SyTest/Identity/Server.pm | 93 ++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/lib/SyTest/Identity/Server.pm b/lib/SyTest/Identity/Server.pm index d18a8f9eb..c2436b711 100644 --- a/lib/SyTest/Identity/Server.pm +++ b/lib/SyTest/Identity/Server.pm @@ -47,9 +47,9 @@ sub _init return $self->SUPER::_init( @_ ); } -=head2 +=head2 rotate_keys - $self->rotate_keys(); + $server->rotate_keys(); Creates new ed25519 public/private key pairs for this server. @@ -68,7 +68,7 @@ sub rotate_keys }; } -=head2 +=head2 on_request Handles incoming HTTP requests to this server. @@ -135,7 +135,7 @@ sub on_request =head2 check_v2 - $self->check_v2 ( $req ) and do_something_else(); + $server->check_v2 ( $req ) and do_something_else(); A helper method that takes an HTTP request and checks if an C parameter matching C<$ID_ACCESS_TOKEN> is present in either the query parameters or the top-level JSON of @@ -159,11 +159,12 @@ sub check_v2 $req->query_param("id_access_token") eq $ID_ACCESS_TOKEN ) { # We found it! - return 1 + return 1; } # Check the JSON body for the token. This isn't required for all endpoints so only try if - # the request has a body + # the request has a body. + # We use an eval in case this request doesn't have a JSON body my $body = eval { $req->body_from_json }; if ( @@ -172,19 +173,19 @@ sub check_v2 $body->{id_access_token} eq $ID_ACCESS_TOKEN ) { # We found it! - return 1 + return 1; } # Couldn't find an access token $resp{error} = "Missing id_access_token parameter"; $resp{errcode} = "M_MISSING_PARAM"; $req->respond_json( \%resp, code => 400 ); - return 0 + return 0; } =head2 on_is_valid - $self->on_is_valid( $req ); + $server->on_is_valid( $req ); Given a HTTP request, check that the value of the public_key query parameter matches a key in the C<$self->{keys}> dictionary. @@ -205,15 +206,15 @@ sub on_is_valid $req->respond_json( \%resp ); } -=head2 +=head2 validate_identity - $self->validate_identity( $medium, $address, $client_secret ); + $server->validate_identity( $medium, $address, $client_secret ); Validates a C, C
combo against a given C. Example: - $self->validate_identity( "email", "heyitsfred@example.com", "apples" ); + $server->validate_identity( "email", "heyitsfred@example.com", "apples" ); Returns the session ID corresponding to the given parameters if one is found. @@ -234,9 +235,9 @@ sub validate_identity return $sid; } -=head2 +=head2 on_pubkey - $self->on_pubkey( $req, $key_name ); + $server->on_pubkey( $req, $key_name ); Given a HTTP request and a key name, return the public key corresponding to that key name if known. @@ -258,9 +259,9 @@ sub on_pubkey $req->respond_json( \%resp ); } -=head2 +=head2 on_v1_lookup - $self->on_v1_lookup( $req ); + $server->on_v1_lookup( $req ); Given a HTTP request containing C and C
query parameters, look up an address/medium combination in the server. @@ -299,9 +300,9 @@ sub on_v1_lookup $req->respond_json( \%resp ); } -=head2 +=head2 on_hash_details - $self->on_hash_details( $req ); + $server->on_hash_details( $req ); Given a HTTP request, this function will respond with a JSON body with a C string containing the server's lookup pepper, and a C array containing all of the @@ -320,9 +321,9 @@ sub on_hash_details $req->respond_json( \%resp ); } -=head2 +=head2 on_v2_lookup - $self->on_v2_lookup( $req ); + $server->on_v2_lookup( $req ); Given a HTTP request containing C, C and C fields in its JSON body, perform a v2 lookup. This involves checking the algorithm that was specified, and whether @@ -409,9 +410,9 @@ sub on_v2_lookup } } -=head2 +=head2 on_store_invite - $self->on_store_invite( $req ); + $server->on_store_invite( $req ); Given a HTTP request with a JSON body containing C, C
, C and C keys, create and store an invite containing them. @@ -465,9 +466,9 @@ sub on_store_invite $req->respond_json( \%resp ); } -=head2 +=head2 on_get_validated_3pid - $self->on_get_validated_3pid( $req ); + $server->on_get_validated_3pid( $req ); Given a HTTP request with a session ID C query parameter, respond with C, C
and C JSON body fields corresponding to the session ID. @@ -493,9 +494,9 @@ sub on_get_validated_3pid $req->respond_json( \%resp ); } -=head2 +=head2 on_bind - $self->on_bind( $req ); + $server->on_bind( $req ); Given a HTTP request containing session ID C and Matrix ID C JSON body fields, bind the medium and address corresponding to the session ID to the given Matrix ID. @@ -536,11 +537,11 @@ sub on_bind $req->respond_json( \%resp ); } -=head2 +=head2 on_unbind - $self->on_unbind( $req ); + $server->on_unbind( $req ); -Given a HTTP request containing a Matrix ID C, +Given a HTTP request containing a Matrix ID C, and a threepid dictionary C, which itself has C and C
fields, remove the binding from the server. If no binding is found, respond to the HTTP request with a C<404 Not Found> error. @@ -569,16 +570,16 @@ sub on_unbind $req->respond_json( \%resp ); } -=head2 +=head2 bind_identity - $self->bind_identity( $hs_uribase, $medium, $address, $user, $before_resp ); + $server->bind_identity( $hs_uribase, $medium, $address, $user, $before_resp ); Shortcut to creating a new threepid identity binding, and calling the C callback of a homeserver specified by C. Example: - $self->bind_identity( undef, "email", $invitee_email, $invitee_mxid ); + $server->bind_identity( undef, "email", $invitee_email, $invitee_mxid ); Store the C and C
as well as the hash of the address for v2 lookup. Finally, call the C endpoint of the HS specified by C @@ -645,15 +646,15 @@ sub bind_identity ); } -=head2 +=head2 lookup_identity - $self->lookup_identity( $medium, $address ); + $server->lookup_identity( $medium, $address ); Shortcut for finding the MXID that's been previously bound to the C, C
combo. Example: - $self->lookup_identity( "email", "bob@example.com" ); + $server->lookup_identity( "email", "bob@example.com" ); Returns the matching Matrix ID, or C if one is not found. @@ -672,9 +673,9 @@ sub lookup_identity return undef; } -=head2 +=head2 sign - $self->sign( $to_sign, %opts ); + $server->sign( $to_sign, %opts ); Sign some data B using the server's private key. Setting C to C<1> will use the server's ephemeral private key for signing instead. @@ -687,7 +688,7 @@ Example: token => $token, ); - $self->sign( \%req, ephemeral => 1); + $server->sign( \%req, ephemeral => 1); =cut @@ -706,15 +707,15 @@ sub sign ); } -=head2 +=head2 invites_for - $self->invites_for( $medium, $address ); + $server->invites_for( $medium, $address ); Retrieve the invites for a C, C
pair. Example: - my $invites = $self->invites_for( "email", "threeheadedmonkey@island.com" ); + my $invites = $server->invites_for( "email", "threeheadedmonkey@island.com" ); Returns a reference to an array of invites that correspond to the given C, C
pair. @@ -729,16 +730,16 @@ sub invites_for return $self->{invites}{ join "\0", $medium, $address }; } -=head2 +=head2 get_access_token - $self->get_access_token(); + $server->get_access_token(); Returns the access token for this server. Required for making calls to authenticated V2 Identity Service endpoints. Example: - my $access_token = $self->get_access_token(); + my $access_token = $server->get_access_token(); =cut @@ -747,9 +748,9 @@ sub get_access_token return $ID_ACCESS_TOKEN; } -=head2 +=head2 name - $self->name(): + $server->name(): Return a string made up of the server's hostname and port, separated by a colon. From 02295d0b93ac87f9a06e56b2952dda3afa3ac35a Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Mon, 9 Sep 2019 14:18:34 +0100 Subject: [PATCH 7/8] Fix colon and remove extra parens --- lib/SyTest/Identity/Server.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/SyTest/Identity/Server.pm b/lib/SyTest/Identity/Server.pm index c2436b711..75c2c45a4 100644 --- a/lib/SyTest/Identity/Server.pm +++ b/lib/SyTest/Identity/Server.pm @@ -732,7 +732,7 @@ sub invites_for =head2 get_access_token - $server->get_access_token(); + $server->get_access_token; Returns the access token for this server. Required for making calls to authenticated V2 Identity Service endpoints. @@ -750,7 +750,7 @@ sub get_access_token =head2 name - $server->name(): + $server->name; Return a string made up of the server's hostname and port, separated by a colon. From d79f8391050f50dc310ef96c0d5b8d3a8d0f7003 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Mon, 9 Sep 2019 14:32:21 +0100 Subject: [PATCH 8/8] Remove more unn. parens. --- tests/30rooms/12thirdpartyinvite.pl | 8 ++++---- tests/54identity.pl | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/30rooms/12thirdpartyinvite.pl b/tests/30rooms/12thirdpartyinvite.pl index 201e52fb0..1384453a0 100644 --- a/tests/30rooms/12thirdpartyinvite.pl +++ b/tests/30rooms/12thirdpartyinvite.pl @@ -11,7 +11,7 @@ my $invitee_mxid = $invitee->user_id; my $room_id; - my $id_access_token = $id_server->get_access_token(); + my $id_access_token = $id_server->get_access_token; $id_server->bind_identity( undef, "email", $invitee_email, $invitee ) ->then( sub { @@ -53,7 +53,7 @@ my $invitee_mxid = $invitee->user_id; my $room_id; - my $id_access_token = $id_server->get_access_token(); + my $id_access_token = $id_server->get_access_token; $id_server->bind_identity( undef, "email", $invitee_email, $invitee ) ->then( sub { @@ -95,7 +95,7 @@ my $invitee_mxid = $invitee->user_id; my $room_id; - my $id_access_token = $id_server->get_access_token(); + my $id_access_token = $id_server->get_access_token; $id_server->bind_identity( undef, "email", $invitee_email, $invitee ) ->then( sub { @@ -475,7 +475,7 @@ sub do_3pid_invite { uri => "/r0/rooms/$room_id/invite", content => { id_server => $id_server->name, - id_access_token => $id_server->get_access_token(), + id_access_token => $id_server->get_access_token, medium => "email", address => $invitee_email, } diff --git a/tests/54identity.pl b/tests/54identity.pl index efc8c9166..a5caff03c 100644 --- a/tests/54identity.pl +++ b/tests/54identity.pl @@ -7,7 +7,7 @@ my $medium = "email"; my $address = 'bob@example.com'; my $client_secret = "a client secret"; - my $id_access_token = $id_server->get_access_token(); + my $id_access_token = $id_server->get_access_token; my $sid = $id_server->validate_identity( $medium, $address, $client_secret ); @@ -42,7 +42,7 @@ my $medium = "email"; my $address = 'bob@example.com'; my $client_secret = "a client secret"; - my $id_access_token = $id_server->get_access_token(); + my $id_access_token = $id_server->get_access_token; my $sid = $id_server->validate_identity( $medium, $address, $client_secret ); @@ -119,7 +119,7 @@ my $medium = "email"; my $address = 'bob@example.com'; my $client_secret = "a client secret"; - my $id_access_token = $id_server->get_access_token(); + my $id_access_token = $id_server->get_access_token; my $sid = $id_server->validate_identity( $medium, $address, $client_secret );