SPA with custom login page. Upgrading Auth0js from v7 to v8

We are currently using version 7.x.x of the auth0js client library and it works great for us in our SPA. We do not rely on auth0lock, we have a need for strongly tailored UI components. So, in our app (client), we create an instance of the Auth0 class (passing in domain & clientId) For login we call the .login(...username, password...) function which relies on /auth/ro (RS256) and store the returned id_token in local storage.

Our middleware adds the bearer token on secured requests to our API & we verify the signature with the shared secret. For token renewal we call .renewIdToken(aboutToExpireTokenFromLocalStorage) which relies on /delegation.

Upgrading to the newest version of auth0js (v8) seems to imply an ‘upgrade’ to HS256 & the usage of the /auth/token endpoint instead. Our assumption was that we simply needed to change our token verification step & instead use the public key to validate the signature (imposing the correct algorithm, HS256, on our JWT library). This worked. We’re not clear at all on token renewal since it no longer works after the upgrade.

As you can see we made some assumptions, with our current implementation being our starting point, it also wouldn’t be easy to completely shift this upside down as you can imagine. So, after going through the current documentation it still isn’t fully clear to us: Generic vanilla JS documentation explains session handling but it doesn’t explain keeping the session alive (I know sessions do not exist, but token renewal isn’t mentioned in the guide): https://auth0.com/docs/quickstart/spa/vanillajs/03-session-handling

The only reference we found for usage in a SPA was on the silent authentication docs: Configure Silent Authentication

In the case of single-page applications, the renewAuth method from auth0.js can be used to perform silent authentication within a hidden iframe, which results in no UX disruption at all.

However this implies having an SSO session and the documentation implies the following:

For this request to succeed, the user must have an active SSO session at Auth0 by having logged in through the hosted login page of your Auth0 domain.

Which we clearly aren’t looking for given our desire to have a custom login for a seamless experience and UI.


Update 1. - Additional Questions (as follow-up to answer by @jmangelo)

Q1)

Would you have an ETA for when an upgrade path is available?

We planned on implementing a custom OTP implementation using the redirect capabilities Auth0 offers via rules: Redirect Users from Within Rules. However, this clearly states that it isn’t compatible with the Resource Owner endpoint (/oauth/ro).

If you have any suggestions on how to move forward or what the strategy is of Auth0 moving forward. Do let us know. Not being able to add OTP is important to us.

Small side question; how would Auth0-lock handle this? I can see from github that it’s using auth0-js v8, so I can only assume that it’s now also calling /oauth/token. How are consumers of this library expected to keep the user authenticated without having to re-enter username/password.

Q2)

Above I quoted from the documentation the following:

For this request to succeed, the user must have an active SSO session at Auth0 by having logged in through the hosted login page of your Auth0 domain.

Is this fully correct? As far as I know a user can log in via a custom form using auth0-js. When the flag SSO=true is there it would still create an SSO session (via the redirect). Would this still be a valid SSO session in scope of the renewAuth functionality in v8?


Update 2. - Additional Questions (as follow-up to answer by @amaan.cheval)

I’m not sure I see the benefits as an integrator of the Auth0 framework, on the contrary. This documentation Auth0 Universal Login shows a custom login page using auth0-js v7 (which should get upgraded to v8 asap). Q3] Isn’t it a bit odd for it to be using the same library as the one that is used on client applications? Shouldn’t this be a subset for usage on the login page? Another factor that supports the library confusion is seeing the non modified login page use this endpoint: /usernamepassword/login (as opposed to /oauth/ro or /oauth/token`).

That being said, I guess we could build and package a custom login app which embeds auth0-js, package/deploy it somewhere and and have it referred from the ‘custom login page’ template (assuming we can) and then bootstrap it with relevant information coming from @@config@@, not ideal from a deployment perspective but doable. But we may well deploy & serve this ourselves, have it deployed under the same domain & make deployment easier.

Q4] So what benefit are we getting from going via the ‘hosted login page’?

The only difference I see is the domain being specific to the authentication step: In regards of user experience we don’t like this since the tenant_id+auth0_domain (we use technical tenant ids) being in the url during the login flow is something we don’t like to expose to the end user. It’s likely to be confusing to them: Q5] Why would they want to provide credentials to a URL that is not related to the initial URL they requested? (we are using an on premise appliance so at least we can get the domain to be the same but for SaaS that argument is mute).

It’s a different story if the auth0 server is just used as an agent in a series of redirects to an IDP, since an end user won’t even notice going via an Auth0 URL.

As a developer, who is very concerned but not fully knowledgeable on security (it’s one of the reasons we rely on Auth0) could you give me some ammunition to use for when we need to argument usage of the hosted login page that goes a bit beyond “It’s more secure”.

If your requirements do not allow for the redirect to the Auth0 hosted login page (which supports customization) then for now you’ll need to keep using Auth0.js v7.

Moving to Auth0.js v8 at the moment and, as you mentioned, implies that the SSO session will need to be established by redirecting to the hosted login page so that you can then later use the approach described in the silent authentication tutorial in order to renew user tokens.

We already discussed and considered improving the possibilities available to people implement highly custom user interfaces that need to be embedded in the client application itself and that at the same time want to move to recent versions of the available libraries. However, at this time this is not yet available so for that very specific scenario you should continue to rely on Auth0.js v7, which is still supported as stated in the associated GitHub repository:

We recommend using auth0.js v8 if you need to use API Auth features. For auth0.js v7 code please check the v7 branch, this version will be supported and maintained alongside v8.


Update:

Q3]

I can relate to your point about the possibility of having only a subset of the library for the use case related to the customization of the hosted login page, but would it really bring anything of value? I suspect it would be more overhead for little benefit. For example, assuming CDN is in use being the exact same script means a possible cache reuse between hosted login page and the client applications themselves. In conclusion, I’m not sure this will change.

Q4]

In general, if you go through the hosted login page then you can leverage more stuff from the service you’re using instead of having to do it yourself in all your client applications custom login pages. For example, the hosted login page can provide built-in protection against cross-site request forgery for the login; depending on your situation and specific client applications this may not even be an issue, but the important take is that going through the hosted login page would get you something for free and one less thing to worry about. However, as it’s almost ever the case, reusing something instead of building it yourself will impose certain restrictions.

At this moment, as @amaan.cheval mentioned, the recommended approach to make use of renewAuth is to have gone through the hosted login page so that a session can be established and the tokens can be renewed based on the session. This can be used through Auth0.js v8; if you can’t make use of the hosted login page then as already mentioned there is not yet an upgrade path and you will have to continue to use Auth0.js v7.

Q5]

This is mostly my opinion, but in general the user should input their credentials only within the domain/system that owns it. If you have App X that allows to login with Google, the user expects to be switched to Google if he has to input their credentials.

The case for an identity provider as a service, like Auth0, is slightly more complex; in truth the credentials are being managed by Auth0 so inputting the credentials at the hosted login page would make complete sense. However, the end-user may not have that perception, depending on how you implemented it. If you implemented sign-up and login through the hosted login page then the user would have this perception and this would be a non-issue, however, if you have a registration process specific to your client application then the user may indeed notice this disconnection between where he registered it and where he logins.

Again, as already mentioned, we’re working on improving the available options for this last scenario in the latest versions of our libraries.

Would you have an ETA for that upgrade?

No ETA, but this is being actively worked upon. As Joao said, this is only if your use-case necessitates using /oauth/ro (i.e. a flow where the user enters their credentials on your client application instead of on Auth0, which is the Identity-Provider in this case).
If you can support redirect based flows, I’d highly recommend you move to using the Hosted Login Page as I detail in this post.

  1. …] Is this fully correct?

To use the renewAuth method, yes, you need to have visited Auth0’s login page (i.e. <your_account>.auth0.com/authorize at some point during the flow. This means that using /oauth/ro (legacy flow) or /oauth/token (OIDC-conformant flow) will neither establish an SSO session for the user for use with renewAuth.

Just to focus our (re)discussion and how we got here:

Initial:

  • We can’t upgrade to v8 flow without drastic changes to our current custom login page
  • Outcome: We keep using v7 since until upgrades are made to make our life easier

Resurrection:

  • We need to use Redirect rules. They are not compatible with /oauth/ro
  • Moving away from /oauth/ro is solved best by ‘upgrading’ v7 to v8 (/oauth/token)

So we’re back to discussing ‘drastic changes’ which implies hosted login pages.

I posted an update to my original answer with additional information in relation to your previous comments. From your summary above, it seems that the upgrade part of your question was somewhat motivated due to the need of the usage of redirect rules and the lack of support for it with the current approach you’re using (Auth0.js 7 - /oauth/ro).

Would you mind posting this as a new question? If your goal is to use redirect rules and custom login pages, then it’s best to start fresh with a new question just focusing on the requirements.

[Q3] Could you elaborate on the endpoint used by the non modified login form: /usernamepassword/login and why it’s different from what (seemingly) the v7 or even the v8 client library would use?

[Q4] I don’t like to establish a session with Auth0 because we seemingly have little control over it. How long would it last? What mechanisms does it use to create and maintain the session? Is SSO enabled by default across clients apps? Etc…
It wouldn’t be just us that would need to know but it’s also something we’d have to justify with our Infosec team.

[Q5] We are indeed the last scenario.

I also understand the duality you have to deal with.
Some client just want to quickly hook up their app with google, facebook, twitter, …
Other clients (like ourselves) are looking for a knowledgeable partner for authentication & easy enterprise IDP integration.

For us, the usage of the Auth0 platform is not something we want to communicate to the user. We tell our clients our product comes with built-in authentication (90% of our users) but there’s an option for IDP integration and we know we can support it.

[Q4_2] Accepting a Auth0 session seems to point us to this as well: https://auth0.com/docs/sso/sso-username-password . The title mentions SSO. But is it about SSO or is it simply about having a session with Auth0? Will a user be able to reuse the session for other clients apps or not?

http://community.auth0.com/questions/2031/redirect-users-from-rules-oauthro

The endpoint you mentioned is not documented as being part of the publicly available Authentication API so even though I could try to give you some information about it the behavior could change or be removed without notice as it’s only internally used so I would prefer to avoid leading you in error and/or in using an endpoint that could change at any minute.

The session is cookie based and the maximum duration is configurable in your account advanced settings. You would then also have to enable each client to make use of that session though the Use Auth0 instead of the IdP to do Single Sign On setting available at the client level.

Ok, that docs page (which I was not aware) basically contradicts one of my initial statements. Although the endpoint the page mentions is not documented in the Authentication API explorer it does have that page so I’ll need to double-check this situation.

I just double-checked; the end result is the same, you should not start to use the /usernamepassword/login as even though it’s mentioned in that page it will be subject to change/removal; hence the reason it’s not listed directly in the Authentication API. Sorry for the confusion, I really thought it was only internal since I was not aware of that page.

The configuration I see in the advanced settings: “This sets the login session lifetime, how long the session will stay valid measured in minutes. The default value is 10080 minutes (or 7 days).”

My current assumption would be to set this to 30 minutes and assume the function renewAuth would extend the session with 30 minutes again. Is this correct?