question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Updating documentation for common use cases

See original GitHub issue

Describe the problem you’d like to have solved

I would love if the documentation for the beta library included a better explanation for a couple common use cases. 100% willing to open a PR to help if I’m able to get some clarification.

After a couple of days of playing around with the library, I’m unsure what the recommended implementation would look like for:

  • Enabling refresh tokens
  • Redirecting a user to login upon access token expiration
  • Enabling MFA on an elective basis

Describe the ideal solution

1. Refresh tokens

It took me an embarrassing amount of time to realize that with this implementation, the refresh token is only created if all of the following things are true:

  1. In the Auth0 dashboard, Applications --> Applications --> Application Details --> Advanced Settings --> Grant Types, Refresh Token is checked.
  2. In the Auth0 dashboard, Applications --> API --> API Settings --> Access Settings, “Allow Offline Access” toggle is set to true
  3. In your environment variables, scope needs to include offline_access

If any of those three are not true, it will fail silently.

However, even when it’s created, I still have questions. The documentation mentions that you can pass { refresh: true } as an option on getAccessToken calls however, the description is not exactly self explanatory (at least not to me).

If set to true, a new Access Token will be requested with the Refresh Token grant, regardless of whether the Access Token has expired or not.

I can read the logic here that essentially says there must be a session.refreshToken && the session.accessToken is expired OR there must be a session.refreshToken && { refresh: true } was passed on the getAccessToken call, but isn’t it the case that all access tokens are requested with the refresh token grant once it has been set in the Auth0 Dashboard --> Applications --> Application Details --> Advanced Settings --> Grant Types area? Is that just a confusing way of saying that you’re rotating the access token if you pass { refresh: true }?

Additionally, even if I did all the three things above and I am successfully creating a refresh token, how long does that last? There seems to be no way of passing any sort of token_lifetime option. Does that mean the refresh token only lasts as long as the session? From what I can piece together on session, you have three levers on SessionConfig to modify that timeline: absoluteDuration, rolling, and rollingDuration.

Defaults are set to 7 days for the absoluteDuration, rolling is set to true, and rollingDuration is set to 1 day. Which per my layman’s understanding would mean that IF you enable / create a refresh token in the session, without changing any defaults, your users have a rolling session that refreshes as long as they are active (any call to Auth0 tenant URL?) once per day. It’s not clear whether this rolling session overrides the absoluteDuration or vice versa. I am assuming that absoluteDuration overrides, which would mean that as long as it has a value, then rolling and rollingDuration are ignored?

If all those things are true, then by enabling refresh tokens & setting absoluteDuration to 30 days, would that make it so a user only needed to log in every 30 days?

2. Redirecting a user to login upon token expiration

From other issues I’ve read, https://github.com/auth0/nextjs-auth0/issues/206 it seems reasonable that profileHandler shouldn’t throw a not_authenticated response because of the refresh token. However, if an access token expires, shouldn’t there be some way that useUser and withPageAuthRequired catch that & redirect to login? How else would the user know that’s why the app just started randomly failing? Is there something I’m missing in terms of config / best practice to make sure that’s not happening to end users?

3. Elective or Optional MFA

From reading the community forums, this seems to typically go unanswered, though I’m not sure why since it seems to be a feature that’s required more and more these days. Per my understanding if you want optional MFA, you need to do the following:

  1. Set up at least 1 Factor in Auth0 Dashboard --> Multi-factor Auth
  2. Make sure the policy is set to “Never”
  3. Create a Rule that looks something like
function multifactorAuthentication(user, context, callback) {
  // Only trigger MFA for this specific application client
  if (context.clientID === {cliendId}) {
  // if user meta data exists & user has MFA set up
  	if (user.user_metadata && user.user_metadata.use_mfa) {
      context.multifactor = {
        provider: 'any',

        // optional, defaults to true. Set to false to force authentication every time.
        // See https://auth0.com/docs/multifactor-authentication/custom#change-the-frequency-of-authentication-requests for details
        allowRememberBrowser: true
      };
 	 }
}
  callback(null, user, context);
}
  1. Either create our own MFA dashboard within our apps OR trigger an enrollment invite via email which would then redirect the user to the Universal Login page, presumably with the prompt:mfa

Outside of the super obvious question of why the only options in MFA Configuration are “Never” and “Always”, my second question is, am I missing something way easier? Is there some way to trigger the Universal Login w/ the MFA screen prompt so that a user who wants to secure their account can easily do so without triggering an email, going to their email client, finding the email, clicking the link, etc.?

Setting MFA to “Always” is absolutely terrible UX for signups but “Never” in today’s day and age is not an option. The UX for the email trigger is super not cool, but if that’s the best we can get for now, then that’s what we’ll do.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
adamjmcgrathcommented, Feb 3, 2021

@mvxt

I have some user_metadata I wanted accessible on the client side, so I created a custom rule that inserts that metadata as custom claims into the ID token. Is this a correct/common use case?

Yep - absolutely fine. The alternative would be to get an Access Token for the Management API and use https://auth0.com/docs/api/management/v2#!/Users/get_users with the scope read:current_user

I have an endpoint that modifies the user_metadata by using the Management client. However, after that metadata is modified, I’m struggling on how to refresh the session’s token to see those updated claim values in the ID token. How do I do this with nextjs-auth0?

If you want a new ID token you need to login again, you could do this non interactively using the prompt=none auth param, eg

// pages/api/auth/[...auth0].js
import { handleAuth, handleLogin } from '@auth0/nextjs-auth0';

export default handleAuth({
  async login(req, res) {
    await handleLogin(req, res, {
        authorizationParams: {
          prompt: 'none'
        }
      });
  }
});

Alternatively, since you have the new user_metadata, you can just update the session with it yourself:

// pages/api/my-api-route.js
import { withApiAuthRequired } from '@auth0/nextjs-auth0';

export default withApiAuthRequired(async function myApiRoute(req, res) {
  const { user } = getSession(req, res);
  await setUserMetaData(newUserMetaData);
  user.user_metadata = newUserMetaData; // <= updates to the session are persisted
});
1reaction
adamjmcgrathcommented, Feb 3, 2021

@austinhale

@adamjmcgrath do you know if setting AUTH0_SESSION_ROLLING=false and AUTH0_SESSION_ABSOLUTE_DURATION=2592000 will work for 30 days or will Auth0 Tenant settings dictating session inactivity override and force everyone to log in again after 3 days?

No, your users will remain logged in for 30 days.

AUTH0_SESSION_ABSOLUTE_DURATION will tell you how long users are logged in to your app, the Auth0 Tenant settings will tell you how long your users are logged in to auth0.com.

Eg. Ignoring inactivity timeout - if AUTH0_SESSION_ABSOLUTE_DURATION is 15 days and the Auth0 Tenant settings “Require Login after” is set to 30 days. A user will be logged out of your app after 15 days, but when they go to login again - they wont be prompted for their credentials on auth0.com, because they’ll still be logged in to auth0.com

Read more comments on GitHub >

github_iconTop Results From Across the Web

8 Tips for Keeping Your Process Documentation Up to Date
If you don't have a plan to regularly update your process documentation, ... Use these eight tips to help your keep your documents...
Read more >
Shifting to Continuous Documentation as a New Approach for ...
Documentation quickly becomes stale as code changes. Continuous documentation focuses on ensuring documentation remains up-to-date and ...
Read more >
3 Situations that are Absolutely Perfect for Use Cases!
3 Situations that are Absolutely Perfect for Use Cases! · Use Cases Can Be Used to Document the Functionality of an Existing System...
Read more >
Technical Documentation in Software Development - AltexSoft
фAll software development products require technical documentation. This article describes tech documentation types, best practices, ...
Read more >
Software Documentation Best Practices [With Examples]
In this guide, we cover software documentation types, examples, and best practices for improving the quality of your documentation process.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found