Wise Monks+Monkees,

I have a Mojolicious Lite app which needs to place a cookie to client for session purposes, after successful login.

It works with Linux+Firefox as expected.

But on an updated/recent apple phone with Safari, it fails. It seems that it does not set the cookie to the browser. What I observe from looking at the phone (not mine) is that the login is successful. But upon redirection to the next page, which is "under" authentication condition and therefore checks if a cookie is set and a session is found, it behaves as if that page was accessed without first authenticating (e.g. "please login first").

This may well be irrelevant information but here it is: The app is hosted on a server with just a static IP. It has no 'domain' name. And it is hosted via nginx, along with other apps each on their own port. Each app is accessed like https://1.2.3.4/app1/login for app1, app2, etc. Nginx detects that, it removes the "app1" prefix and sends the request to the appropriate port WITH the added header "X-Request-Base". The app detects that header and passes it on to templates in order to prepend each reference to the app's url with the "app1" prefix. This works just great for all my apps. And I am mentioning it here just in case it makes a difference with Safari. Perhaps it freaks out seeing that extra header.

The other information is that I am using a self-signed SSL certificate (for said host). This means, I can access my apps via https://1.2.3.4/app1/login with Firefox and Chrome warning about "Warning: Potential Security Risk Ahead" (click "Advanced" and then "Accept the Risk and Continue"). But getting there eventually.

Safari warns about the Risk, goes to the Login page, but then it does not save the cookie when user credentials are correct. I know because it is redirected to the next page which is under authentication and says to go back and login properly.

Because, internally, my app does not use mix-mode HTTP[S], but *only* HTTPS, I am using "secure" cookies. Would that make a difference with Safari?

BTW, I do not have access to that Safari at this moment, so I can't answer anything else.

The test Mojo app below is run with MOJO_MODE=production hypnotoad myapp.pl and accessed on http://localhost:3000. PLEASE NOTE that it is HTTP-mode only. So that may cause it to succeed with Safari - please let me know.

The first time is run, the page shows that there is no session (no cookie/the user is not "logged in"/etc.) and it proceeds to create a session. The effect of which will be observed upon reloading which should tell you that it has received some stash-data from the server (which is stored in the session).

As I have no access to Safari at the moment, I don't know if this test app will exhibit the problem I encountered. But it is a a very slim version of how my real app is.

Also note that I don't set any third-party cookies neither I access any 3rdparty links from my app (even my CSS/JS are all stored on the same server with the app) EXCEPT an embeded google map on the page which is accessed after login authentication. That is, it is accessed only if the cookie is set! I have included the iframe in the test app below, one can uncomment it to test further.

Oh, my app uses Text::Xslate templating framework. But for simplicity I am here using Mojo's ep. One can uncomment a couple of lines below to switch to Xslate.

And here is the test app:

#!perl # MOJO_MODE=production hypnotoad myapp.pl use strict; use warnings; use Mojolicious::Lite; use Mojo::Log; # if you enable this then you need to set # render handler to 'tx', like this: # $c->render( ... 'handler' => 'tx' ...) #plugin 'xslate_renderer'; my $PORT = '3000'; my $COOKIENAME = 'cook'; my $log = Mojo::Log->new(); # make sure you set the secret because it defaults to the app's name!! +! # cookie name and secret must be different for different apps. app->secrets(['ajhgdauyda']); # secure cookies are those sent over HTTPS only # so if part of the app is over HTTP, the cookie will not be sent! app->log->level('info'); app->sessions->secure(1); app->sessions->cookie_name($COOKIENAME); $log->info("session cookie is '$COOKIENAME'."); # this is important if nginx is rewriting the url (e.g. handling multi +ple sites # it removes part of the url but we know the original and we must appe +nd it # on each request we make app->hook( before_dispatch => sub { my $c = shift; if ( my $base = $c->req->headers->header('X-Request-Base') ) { $log->info("found base '$base' and setting it ..."); my $u = Mojo::URL->new($base); $c->req->url->base($u); # this will go to the templates $c->stash('RequestBaseHeader' => Mojo::URL->new($u->to_abs +)); } else { $c->stash('RequestBaseHeader' => ''); } } ); ############################################################ # end of startup, start the routes ############################################################ get '/' => sub { my $c = $_[0]; if( exists($c->session->{'u'}) && defined($c->session->{'u'}) ){ # we have a session, read it and send it to the template # to print some content. $log->info("session found and sent to template ..."); $c->stash( 'd' => $c->session->{'u'} ); } else { # there is no session, set it $log->info("setting the session ..."); $c->session->{'u'} = {'hello' => 'hello i am session content'} +; $c->stash( 'd' => undef ); } $c->render( 'template' => 'checksession', # down in __DATA__ 'format' => 'html', 'handler' => 'ep', ); }; my $daemon = Mojo::Server::Daemon->new( app => app, listen => ["http://*:${PORT}"] ); $log->info("$0 : started listening on port ${PORT} and with mode ". ap +p->mode ." ..."); $daemon->run; #app->start; __DATA__ @@ checksession.html.tx <!doctype html> <html> <head></head> <body> <p> : if( $d == nil){ <p> No session yet, hopefully it has been set now! <p> Reload the page to see if it has been set. : } else { <p> You have session with this content: : for $d.keys() -> $k { '<: $k :>' =&gt; '<: $d[$k] :>' : } : } </body> </html> @@ checksession.html.ep <!doctype html> <html> <head></head> <body> % if( defined $d ){ <p> You have session with this content: % for my $k (keys %$d){ key='<%= $k =%>' = '<%= $d->{$k} =%>' % } <!-- the map: <div> <iframe src="https://www.google.com/maps/embed?pb=!1m14!1m12!1m3!1d828 +424.0952114153!2d9.034434313613875!3d40.04401928099502!2m3!1f0!2f0!3f +0!3m2!1i1024!2i768!4f13.1!5e0!3m2!1sen!2s!4v1731351850009!5m2!1sen!2s +" width="600" height="450" style="border:0;" allowfullscreen="" loadi +ng="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe> </div> --> % } else { <p> No session yet, hopefully it was set! <p> Reload the page to see if it has been set. % } </body> </html>

Edit: Thanks to the information provided by sectokia and karlgoethebier I have confirmed that Safari saves the cookie, in situations as above, when I do not use secure cookies but "plain", e.g. app->sessions->secure(0);. This is a quasi-solution because my settings, in this particular case, are for testing an app. Eventually the app will be migrated to host with "proper" certificates in the future. Thank you both!

bw, bliako


In reply to [Solved] Safari (apple) fails to set cookie from Mojo Lite app by bliako

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.