Closed hussam-qasem closed 1 year ago
I think if you drop the "You're not Authenticated" line, things might work better for you
Thank you @oetiker for the prompt response. True, when I drop the render
line, I do get authenticated; however, it goes no where afterwards. In the logs, I get:
Nothing has been rendered, expecting delayed response
Here's a full example demonstrating the problem - just replace ad_server
in startup
:
script/my_app
#!/usr/bin/env perl
use strict;
use warnings;
use Mojo::File qw(curfile);
use lib curfile->dirname->sibling('lib')->to_string;
use Mojolicious::Commands;
Mojolicious::Commands->start_app('MyApp');
lib/MyApp.pm
package MyApp;
use Mojo::Base 'Mojolicious', -signatures;
# Run once at server start
sub startup ($self) {
$self->secrets('s3cret');
$self->plugin('SPNEGO',ad_server => 'my_ad_server.example.com');
my $r = $self->routes;
$r->get('/')->to('Example#index');
my $auth = $r->under('/' => sub ($c) {
# Authenticated
return 1 if $c->session('user');
# NTLM Auth
$c->ntlm_auth({
auth_success_cb => sub {
my $c = shift;
my $user = shift;
my $ldap = shift; # bound Net::LDAP::SPNEGO connection
$c->session('user',$user->{samaccountname});
$c->session('name',$user->{displayname});
my $groups = $ldap->get_ad_groups($user->{samaccountname});
$c->session('groups',[ sort keys %$groups]);
return 1;
}
});
# Not authenticated
#$c->render(text => "You're not Authenticated", status => 401);
return undef;
});
$auth->post('/')->to('Example#search');
}
1;
lib/MyApp/Controller/Example.pm
package MyApp::Controller::Example;
use Mojo::Base 'Mojolicious::Controller', -signatures;
sub index ($self)
{
return $self->render(inline => '<html><body><form method="post"><textarea name="numbers" maxlength="11">123</textarea><button type="submit">Go</button></form></body></html>');
}
sub search ($self)
{
my $v = $self->validation;
$v->required("numbers");
return $self->render(text=>"Validation Error") if $v->has_error;
my $numbers = $v->param("numbers");
my @numbers = split(/\r?\n/, $numbers);
Mojo::Promise
->map(
{concurrency => 2},
sub {
$self->ua->get_p("https://httpbin.org/delay/1?q=$_" => {'api-key'=>'shhh'});
}, @numbers)
->then(
sub{
my @results = @_;
my @json = map { $_->[0]->res->json } @results;
return $self->render(json => \@json);
})
->catch(
sub {
my $err = shift;
return $self->render(text => $err);
})
->wait;
#return $self->render(text => "This shall result is 'Unhandled rejected promise: A response has already been rendered'");
}
1;
The problem with your code is that you are not looking at the result of the ntlm_auth code … since you are running this inside under
I guess the following should do:
my $ret = $c->ntlm_auth(
auth_success_cb => sub {
[...]
return 1;
}
);
if ($ret) {
# if the call returns 1 the authentication has been successful, so 'under' must return nothing.
return;
} else {
# if authentication is in progress, $ret is empty, so `under` must return 1 to stopp futher processing.
return 1;
}
Thank you @oetiker for your time and response.
What you suggested works! Now I need to fix my Mojolicious code and figure out how to render correctly from a promise.
Unhandled rejected promise: A response has already been rendered
In a full Mojo App, the example code works well if copied it inside each controller. However, I can't figure out how to call it during application
startup
. For example, in mystartup
:When I perform
POST
, no authentication occurs and I get the following errors:If I comment-out the
$c->render
line, authentication occurs, but I get:and no results are rendered.
Would you kindly point me to where I've gone wrong?
Thank you!