1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- package Trog::Authz::Matrix;
- use strict;
- use warnings;
- no warnings 'experimental';
- use feature qw{signatures state};
- use parent 'Trog::Authz::Base';
- use Trog::Auth ();
- use HTTP::Tiny ();
- use constant 'required_params' => [ 'extAuthData' ];
- sub do_auth ($self) {
- die "Please setup an admin user first" if !$self->{'params'}{'hasusers'};
- $self->failed(1);
- require JSON::XS;
- my $decoded;
- eval { $decoded = JSON::XS::decode_json($self->{'params'}{'extAuthData'}); };
- return $self if !$decoded;
- # XXX TODO potential security/DOS issue -- How does one prevent spoofing on this end?
- # For example, user POSTs the json blob with the right param names, etc. but no
- # actual auth gating -- Suddenly you have a user and session more or less out of
- # whole cloth with no auth ever done. Only thing I can think of to prevent this
- # is more or less "after the fact" via calling `isSignedIn()` as part of pageload
- # when you are a matrix user, invalidating the session if not.
- # I'm sure you can already tell the hole in this perfect plan -- "just disable js".
- # The only real way I can think of for now to prevent abuse here is to do a check
- # on the backend using the access token and user just to do some kind of ping check.
- # That said this still just makes it "harder" to pull off bullshit. Only way to be
- # 100% sure we are talking to a matrix server would be to do it all on the backend.
- # That said, this is probably "good enough" for now.
- my $ping_url = $decoded->{'well_known'}{'m.homeserver'}{'base_url'};
- $ping_url .= "/_matrix/client/r0/presence/$decoded->{'user_id'}/status";
- $ping_url .= "?access_token=$decoded->{'access_token'}";
- my $resp = HTTP::Tiny->new->get($ping_url);
- return $self unless $resp->{'success'};
- # I'm using ACLs here as a proxy for the user existing.
- # That may? be a bad assumption. If so I need to make another sub for getting this.
- my @acls = Trog::Auth::acls4user($decoded->{user_id});
- if(!@acls) {
- # Create the user XXX TODO -- Have a config param for "extra" ACLs the admin
- # can assign in the UI/Config in order to give them other "default" ACLs like
- # access to private content or ability to comment on articles, etc.
- my $cfg = Trog::Config::get();
- Trog::Auth::useradd(
- $decoded->{user_id},
- 'Matrix', # Never used here, so just put in the ext auth provider name.
- [ 'extAuthUser' ], # This ACL is important, and should be non-removable.
- );
- # By default, the avatar is cropped to 20x20, let's get a larger one if available.
- my $avatar_url = substr( $decoded->{avatar_content}, 0, index( $decoded->{'avatar_content'}, '?' ) );
- $avatar_url .= "?height=120&width=120&method=crop";
- my $dat = Trog::Data->new($cfg);
- $dat->add(
- {
- title => $decoded->{user_id},
- data => $decoded->{displayname},
- preview => $avatar_url,
- wallpaper => '/img/sys/testpattern.jpg',
- tags => ['about'],
- visibility => 'public',
- acls => ['admin'],
- local_href => "/users/$decoded->{user_id}",
- callback => "Trog::Routes::HTML::users",
- method => 'GET',
- user => $decoded->{user_id},
- form => 'profile.tx',
- aliases => [],
- },
- );
- }
- # Check if banned
- return $self if grep { $_ eq 'banned' } @acls;
- my $cookie = Trog::Auth::mksession( $decoded->{user_id}, 'Matrix' );
- $self->handle_cookie($cookie);
- $self->failed(0);
- return $self;
- }
- 1;
|