MVC5: Limit user access and sign-up based on roles

I have a question / issue regarding an MVC5 project that uses Auth0 components.

So far, I have been able to implement the standard sign-up login using Auth0 components based on the quickstart examples. Users can sign up using an email address and a password. However, at the moment, anyone can create a user for this application and sign-up with any given email address.

A new requirement is that access be limited to users based on predefined user roles, meaning that users and their roles are created beforehand. No one else, apart from these predefined users, should be able to login to the application. In order to facilitate the process, I would assume that it would be necessary to get rid of the sign-up button / feature in the default Auth0 login form.

In the documentation I read about Custom Signup, but as far as I understood, this applies only to SPAs and I was not able to figure out how I would implement something along these lines in an MVC5 project. I also came across creating a White List, but the example only
showed how to add email addresses. In the present scenario, roles would be defined. One question would be if one could apply roles instead of
email addresses when creating a White List.

The overall goal is roughly this: Unless the user is assigned the role of let’s say Contributor s/he cannot access the application, Sign-up should be disabled in general,
since users and roles should be created by Auth0 admin.

Which steps would I need to take in order to allow role-based access for predefined users and disabling the sign-up features in the default Auth0 login with the least amount of code changes?

I would like to apologize in advance if my request might be unclear, since this is the first time I am using Auth0.

Please do get back in touch should you require additional information. I am looking forward to your replies.

Thanks a mil in advance.

Chris

Hi @cres, welcome to the community!

There are a few choices on how to achieve this.

At the Auth0 level, for database connections, there is one basic decision (configured for each database connection):

  • Allow public signups: anyone can create a user in the system. Internally, it means that the /dbconnection/signup (docs here) is enabled for that connection. Lock, the UI widget, uses that endpoint to create the user (if it is enabled).
  • Don’t allow public signups: users don’t get to create an account in Auth0. An application authorized to use the Management API v2 with the create:users scope (for the Create User endpoint).

As for the authorization information (users allowed in the system and roles membership), you can store it in Auth0 or in a separate database.

If you plan on keeping the roles and users information in Auth0 itself, you’ll have no option but to create the users in advance. This could be done either through a backend app that talks to Auth0’s Management API, or simply through the dashboard UI. You can assign an unguessable password and tell your users to go through the password reset flow (click on “Forgot your password?”) when logging in for the first time. You can check the role membership requirement in a rule or send the rule membership information as a claim so that the application can read it and decide what to do with the user (something like “Hey it looks like you don’t have the right role to access this app”).

If you’ll have a list of allowed users and their roles on a separate database, you can host a “User signup” page in your application where you’d:

  • Get the user’s email address
  • Check if the user is allowed to signup
  • If so, ask for a password, create the user in Auth0 via the management API v2. Tell the user to log in.

Again, you can use a rule to verify the role membership and stop authorization right away, or put the role as a claim in the ID token and let the application decide what to do next.

These are some basic options, but the building blocks are there to tailor the user experience to your needs. Hope that helps a bit.

Dear Nicolas,

Thanks a mil for getting back to me regarding my query. I had a go at the links you kindly provided. I must admit that, with all the information acquired, I am now a bit confused about how to proceed.

Like I mentioned, I set up a “conventional” Auth0-Login with sign-up as demonstrated in the quick start examples. I assume from what I read that, in order to create a login for pre-defined users, I also would have to the Auth0-API. At the moment I am having trouble picturing where to start:
Would I need to extend the existing setup by adding classes and methods handling the API and passing the information back to the existing application components?
Is there perhaps a sample application or a manual describing these steps?

Moreover, I am still a bit confused about what needs to / can be done using the dashboard?

It would be grand if you or somebody else could elaborate a bit and provide me with a starting point.
My main concern is that I do not wish to change a lot in the setup I already created.

Looking forward to your reply.

Kind regards

Chris

Perhaps it might be better to backtrack just a bit and go over some of the basics.
How does authentication work with a regular web app like an MVC app?

  • These apps usually keep a session for the user. A user logs in (with whatever method) and the app creates a session (by using a cookie) to keep the user logged in for the duration of the session. This is handled by the “cookie middleware” in the ASP.Net framework.
  • The cookie middleware puts claims about the user in the session. Claims are pieces of information about the user, like an ID, an email address, name and so on. Each time there’s a request from the user, the cookie middleware parses the session cookie and makes all the session information available in the request pipeline, so that you can check for this.User in your controllers.
  • When a user first lands on the app and there’s no existing session (the app doesn’t know who the user is), then you need to authenticate the user. The most basic options for this are:
    • Authenticate the user directly in your app. Ask for credentials (email/pwd), check against your own database. If they match, you create the session cookie (again, using the cookie middleware).
    • Send the user to an external identity provider, like Auth0. In the case of Auth0 and others, this is done through the OpenID Connect middleware. Basically you redirect the user to the IdP, the IdP does its job, and redirects back to the app’s callback endpoint. In the callback, the OIDC middleware processes the response from the IdP and talks with the Cookie middleware to set up a session for the user based on the response.

The above is for login. For signups, two separate choices:

  • Public signups. Anyone can create a user. Most online services work like this, even for paid or subscription services, because you want as little friction as possible. If you want to charge the user for the services, you can do that later from the application, but authentication (knowing who the user is) happens regardless of whether the user is an “approved” user.
    • If working with external identity provider, this can mean letting the user sign up when asked to log in. This is what Auth0 calls “Public signups”. It’s the “Sign up” tab presented when logging in.
    • You can also chose to handle the whole signup flow from the app itself. In this case, after you’ve gathered all the information you require for signup (email and password at a minimum) you can talk to Auth0 in a server-to-server fashion using the Management API v2 to create a user.
  • No public signups. Someone else creates the identity for the user, like an administrator. This is most common in enterprise applications. In this case you can:
    • Use a backend application, a directory service, an IAM software that “provisions” (creates) the user in the necessary places.
    • If using Auth0, you can create the user in Auth0 using the dashboard. This might not be enough for your use case, as maybe the user has some information stored in your own database.

Perhaps a simple solution for the use case you mentioned in the first post would be:

  • Turn off signups for the Auth0 database you’ll be using (so no one can sign up)
  • Create users manually from the dashboard (in the “Users” section).
  • Only users that you’ve created in the dashboard will be able to log in.

The above, of course, can be polished into something much more sophisticated. That depends on the experience that you are after. Hopefully the description above can help you clarify the overall design before getting into the specifics of classes and methods.

Dear Nicolas,

Thanks a mil for elaborating on the matter and hand. Thanks for pointing out the different approaches one might take. While reading through your post, I realised that my description of the initial scenario had not been quite accurate.
It is true that I set up the standard sign-up login using Auth0 components, however I did not create any databases for user registration, because I intended to let Auth0 handle this. Based on your explanations, I think I might opt for creating users directly in the Dashboard.

The question remains how to modify the Login-Form in order to provide just a login and a password retrieval button / control element, or will the initial Login be modified automatically depending on my mode of user registration?

I’ll try out entering users directly into the Dashboard to see what that brings about, since I guess this is the intended approach.

Looking forwarding to your reply and thanks again for your help.

Kind regards

Chris