47

Here is the code in my base.html header

    <script>
        var auth_status = "{{ user.is_authenticated }}"
    </script>

    {% block scripts %}  {% endblock %}

The rest of the scripts in my site are in the block scripts.

In a child template (within the script block and within script tags) I have this code,

         if (auth_status) {
          //something
         }

The error at hand is auth_status is always True, when it should be on and off depending on if the user is logged in. Request_context is being passed to the template so that should not be the error.

Thanks

7
  • 3
    Sightly unrelated to your question, but be aware than doing if (user_is_authenticated) { do stuff; } can be a security issue if you actually rely on the value of this JS variable. An user could modify the value of the JS variable before execution. Commented Sep 12, 2012 at 20:36
  • So your saying a user can somehow set auth_status = true? So would bypassing the js var be a valid workaround? Ex: if({{ user.is_authenticated|yesno:"true,false" }}) versus if(auth_status) ?? Commented Sep 12, 2012 at 20:46
  • 2
    A malicious user could just pull the source code of your page and replace whatever they want with... whatever they want. There is no way you can implement any security client-side (that is, in JS) and there is no workaround, all security / access control must be done server-side (that is, in your Python code). JS is not an extension of your application code that's executed dynamically, it's something different, with different constraints. Commented Sep 12, 2012 at 20:49
  • Wait, so even django's template variables are at risk of people tampering with? Would a reasonable solution be to have anything that requires user_auth be a html POST? Commented Sep 12, 2012 at 20:58
  • 2
    Yes, you can safely use request.user.is_authenticated() in python code. It's OK to use {% if user.authenticated %} in template code, as this will be computed server-side, that is, before the HTML is sent to the client. The generic rule of thumb is that anything that gets to the client can be altered, anything that never gets to them can't. (At least, not in this way ;) ) Commented Sep 12, 2012 at 21:32

3 Answers 3

138

For what I see your auth_status variable seems to be a string, not a boolean. A variable with a non-empty string on javascript will evaluate to true on an if clause.

Anyhow, something like

<script>
    var auth_status = {{ user.is_authenticated }};
</script>

will not work because that will generate this HTML:

<script>
    var auth_status = True;
</script>

As Python's True boolean is uppercased.

This should do the translation from Python to Javascript:

<script>
    var auth_status = {{ user.is_authenticated|yesno:"true,false" }};
</script>

Check yesno docs here: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#yesno

Sign up to request clarification or add additional context in comments.

4 Comments

Wow! Thanks so much, I completely overlooked the uppercase/lowercase difference in the two languages!
A more general solution for passing Python vars through to JS vars is to use json. In py: context['foo'] = json.dumps(a_py_list). In template <script>var js_foo = {{foo|safe}}</script>. This will work for most data structures, and also for booleans.
@Sean I don't think it is a good idea to be using json to dump your Python values into a Javascript-safe represenation when you first put the values in your context because you can't be sure in the handler if it will be used as a JS value or as Python in a Jinja template for example. If, in my Jinja template I want to use code like {% if myBool %}, it won't work properly if myBool has a string value instead of a Python bool.
@Jesse: I hadn't considered there could be confusion, but you are right. I should clarify that I only do this for the vars I need in JS, not all vars in the context. And usually it is an aggregation of more complex data into a single dict, that in JS becomes an object. Do you know another way to solve the general problem of passing backend vars to JS on initial page load? Not an ajax app, just a single load and then some JS that needs initialising with data from the server.
6

Another option would be to use the jinja2 tojson filter:

<script>
  let javascript_var = {{ python_var|tojson }};
</script>

You may also want to use the safe filter depending on what you're passing:

<script>
  let javascript_var = {{ python_var|tojson|safe }};
</script>

1 Comment

This is as older version.
-1

solution for 2022:

<script>
const isAuthenticated = ${str(user.is_authenticated).lower()}
</script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.