Using anvil.server.session to store previous state

My app has an external authentication step. I want to store the user in such a way that when I return to the app later, I can set the system up with the logout option set rather than the login; the user had already logged in to the external session.

I have tried setting the session up using the server functions below. However when I stop and run in development, the user has disappeared. The same happens with closing and opening a tab.

@anvil.server.callable
def set_session(user):
  anvil.server.session["user"] = user
  
@anvil.server.callable
def get_session():
  return anvil.server.session.get("user", "unknown")

Perhaps I am misunderstanding the role of anvil.server.session and should use the database table for this.

Any suggestions?

I am accessing an webId-OIDC resource via your my Anvil app. I have to run their authentication routines in javascript. So I have a custom HTML and script that does that for me. I then thought that the fact that I had successfully authenticated against the external app could be stored somewhere for retrieval later. Hence my interest in using the anvil.session for this.

I think you might do better to create a cookie for this.

See here : https://anvil.works/doc/#cookies

This will create a persistent state across requests based on arbitrary data.

That said, I may have misunderstood you…

I will look at your reference thanks. I think that the authentication process left a cookie already and I may be able to access this.

I’m not sure that a cookie created by an external resource will be available to Anvil. I’m not sure about that to be honest, but I think there will be no reference for Anvil.

So instead of setting a session state, set a cookie instead.

I thought that too. When I was using the IFrame, that is definitely the case. But using the custom HTML, the authentication is using javascript within the Anvil environment, so I think I might be able to find it. I will write a bit of code to look at all the cookies in the Anvil session.

1 Like

Hey,

I think it would help to clarify a bit what you’re trying to do! You’re authenticating against an external application, and then storing that fact in Anvil, correct?

(This turned into a long ramble about authenticating against other web services. Long story short, it’s a little bit complicated; this is why we built the Users service to make it easy to authenticate against common web services like Google, Office 365, or Facebook.)

First step first: This requires communicating between your external app and Anvil, in a way that can’t be faked. This is tricky and easy to get wrong - this is why services like Facebook and Google have standardised on the OAuth protocol. You can implement OAuth with HTTP endpoints - basically, you redirect the browser to a URL on the other service, then the other URL redirects you back after login with an authentication token that you then validate. (OAuth is a little bit more heavyweight than you need if you control both apps, but there are more subtleties to doing it safely than I have room to describe here.)

Once you have communicated to your server code in a trustworthy way that the user is successfully logged in, then @david.wylie is spot on about the best way to store it. Anvil Cookies are encrypted and authenticated, so you can trust that any cookie value is there because you set it.

However, Anvil cookies cannot be reliably deleted, so there is no built-in way of communicating from your . So what I would recommend is, instead of setting a cookie like anvil.server.cookies.local['username'] = 'simon.m.shapiro', you instead record an authentication token that can be checked against your authentication service. Then, when a user opens your app, you make an HTTP request to your authentication service to check that token is still valid, before letting them do anything. When they log out of the authentication service, those tokens will cease being valid, so they won’t be logged into your Anvil app any more either.

(This loosely corresponds to the idea of “refresh tokens” in OAuth.)

1 Like

Thanks. In fact the external app is WebID-OIDC compliant. It is the Solid Server provided at Inrupt.net.

The Solid project provides JavaScript sdks for logging in. I am using them in custom html to authenticate which works fine.

My last remaining problem is to run the “have you already authenticated?” JavaScript function on startup. The init of the main form tells me to rely on the ‘form_show’ function in the custom html which then tells me the Javascript library isn’t available (yet). So I thought I could store it somewhere when I first authenticated and then come back later to retrieve it.

Admittedly this is a work around. As the first prize would be to run the JavaScript function.

The init of the main form tells me to rely on the ‘form_show’ function in the custom html which then tells me the Javascript library isn’t available (yet).

Are you importing the JavaScript library using Native Libraries? Anything you write in there goes into the <head> of the Anvil app, so it should get loaded before form_show runs.

1 Like

Hi Shaun,

Native Libraries works perfectly :smile:

Many thanks.

1 Like