perlsky is a Perl 5 implementation of an AT Protocol Personal Data Server.
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fail closed without jwt secret

alice 22b32ad3 e7a84fac

+51 -3
+1
docs/DEPLOYMENT.md
··· 79 79 - `base_url`: the public HTTPS origin for the PDS 80 80 - `hostname`: the host relays should crawl 81 81 - `service_handle_domain`: the suffix used for local handles 82 + - `jwt_secret`: required; the server now refuses to start if it is missing or still set to the old `perlsky-dev-secret` fallback 82 83 - If you want users like `alice.pds.example.com`, set `service_handle_domain` to `pds.example.com`, not `example.com`. 83 84 - Public handle resolution for `alice.pds.example.com` also requires wildcard DNS for `*.pds.example.com` and a reverse proxy/TLS setup that will answer those subdomains. 84 85 - `invite_code_required`: if true, `createAccount` requires a valid invite code
+12 -1
lib/ATProto/PDS.pm
··· 23 23 use ATProto::PDS::ServiceProxy; 24 24 use ATProto::PDS::Store::SQLite; 25 25 use ATProto::PDS::XRPC::Dispatcher; 26 + use Carp qw(croak); 26 27 use File::Spec; 27 28 28 29 has project_root => ''; ··· 31 32 sub startup ($self) { 32 33 my $config = $self->settings; 33 34 my $root = $self->project_root; 35 + my $jwt_secret = _require_jwt_secret($config); 34 36 my $public_url = Mojo::URL->new($config->{base_url} // 'http://127.0.0.1:7755'); 35 37 my $metrics = ATProto::PDS::Metrics->new( 36 38 service => $config->{service_name} // 'perlsky', ··· 42 44 metrics => $metrics, 43 45 ); 44 46 45 - $self->secrets([$config->{jwt_secret} // 'perlsky-dev-secret']); 47 + $self->secrets([$jwt_secret]); 46 48 $self->hook(before_dispatch => sub ($c) { 47 49 return unless _cors_path($c->req->url->path); 48 50 ··· 205 207 routes => $routes, 206 208 catalog => endpoint_catalog($root), 207 209 )->register_routes; 210 + } 211 + 212 + sub _require_jwt_secret ($config) { 213 + my $jwt_secret = $config->{jwt_secret}; 214 + croak 'jwt_secret must be configured' 215 + unless defined $jwt_secret && length $jwt_secret; 216 + croak 'jwt_secret must not use the legacy perlsky-dev-secret default' 217 + if $jwt_secret eq 'perlsky-dev-secret'; 218 + return $jwt_secret; 208 219 } 209 220 210 221 sub _cors_path ($path) {
+11 -2
lib/ATProto/PDS/API/Server.pm
··· 621 621 unless $auth =~ /\ABearer\s+(.+)\z/i; 622 622 my $token = $1; 623 623 624 - my $decoded = eval { decode_jwt($token, $c->config_value('jwt_secret', 'perlsky-dev-secret')) }; 624 + my $decoded = eval { decode_jwt($token, _jwt_secret($c)) }; 625 625 if (my $err = $@) { 626 626 my $message = "$err"; 627 627 my $code = $message =~ /expired/i ? 'ExpiredToken' : 'InvalidToken'; ··· 674 674 675 675 sub _session_response ($c, $account, $session) { 676 676 my $issuer = service_did($c->app->settings); 677 - my $secret = $c->config_value('jwt_secret', 'perlsky-dev-secret'); 677 + my $secret = _jwt_secret($c); 678 678 my $now = time; 679 679 my $scope = _canonical_access_scope($session->{scope}); 680 680 my $refresh_exp = $session->{expires_at} // ($now + (30 * 24 * 60 * 60)); ··· 709 709 return TOKEN_AUD_ACCESS unless defined $scope && length $scope; 710 710 return TOKEN_AUD_ACCESS if $scope eq 'atproto'; 711 711 return $scope; 712 + } 713 + 714 + sub _jwt_secret ($c) { 715 + my $secret = $c->config_value('jwt_secret'); 716 + xrpc_error(500, 'ServerMisconfigured', 'jwt_secret is not configured') 717 + unless defined $secret && length $secret; 718 + xrpc_error(500, 'ServerMisconfigured', 'jwt_secret is using the legacy dev default') 719 + if $secret eq 'perlsky-dev-secret'; 720 + return $secret; 712 721 } 713 722 714 723 sub _normalize_lxm ($lxm = q()) {
+27
t/app.t
··· 56 56 ->status_is(401) 57 57 ->json_is('/error' => 'AuthRequired'); 58 58 59 + my $missing_secret_error = eval { 60 + ATProto::PDS->new( 61 + project_root => $root, 62 + settings => { 63 + base_url => 'http://127.0.0.1:7755', 64 + service_did_method => 'did:web', 65 + service_handle_domain => 'localhost', 66 + }, 67 + ); 68 + undef; 69 + }; 70 + like("$@", qr/jwt_secret must be configured/, 'startup fails closed without jwt_secret'); 71 + 72 + my $legacy_secret_error = eval { 73 + ATProto::PDS->new( 74 + project_root => $root, 75 + settings => { 76 + base_url => 'http://127.0.0.1:7755', 77 + service_did_method => 'did:web', 78 + service_handle_domain => 'localhost', 79 + jwt_secret => 'perlsky-dev-secret', 80 + }, 81 + ); 82 + undef; 83 + }; 84 + like("$@", qr/jwt_secret must not use the legacy perlsky-dev-secret default/, 'startup fails closed on the legacy dev jwt secret'); 85 + 59 86 done_testing;