Imagine a situation where you have to build a flexible REST backend API to support mobile and single page apps with end users, external automated process and other clients, like 3rd parties, in the future. You will quickly realize that security topic is very complex and time consuming. This is an overview of the problem and solution I suggest – the Auth0 platform.
There are many terms, technologies and strategies for this problem: basic authentication, tokens, JWT, keys/secrets, OAuth.. There are also many scenarios: internal APIs, public APIs, many different types of clients, mobile apps, single page apps, real users, machine clients, etc. So just to understand the full picture and be able to choose the right strategy for your case, it’s necessary to spend a lot of time and research.
Then we also have many other typical things to cover: user management, registration, login, passwords, SSO, social integrations, MFA, expiry, timeouts, invalidation/blocking, reset, emails, analytics and so on.
We also have to implement all this in our product. It’s obvious that just security aspect will probably take a few sprints. And it’s really important because it’s about security.
Then when we move to a new product – same story again. Is there an easier way? Fortunately there is, welcome to Auth0!
What is Auth0?
Auth0 is an awesome platform to help us with authentication/authorization and all other concerns that I mentioned. They have free and paid plans, great documentation, libraries, community and support.
When you register, you will be able to create multiple, so called, tenants – your products basically. So it’s easy to manage and switch between all your products from one central place just by selecting them from the dropdown – then the whole experience/UI is focused on the selected product / tenant.
You can create backend APIs, different types of clients, set permissions, manage users and almost everything you can imagine. Auth0 is auth as a service. You can think of Auth0 as security aspect/module of your product.
Let’s now focus on our example from introduction and illustrate how it works.
The first step is to create an API for your backend, everything happens around it. You can set timeouts, signing algorithm and define scopes that will be sent in access token from clients to tell if request has permission to do something.
Machine to Machine App
In the Application section we can define different clients. They can be: Native (mobile, desktop), SPAs, regular web apps or machine to machine app (CLI, daemon or any other service/process).
We want to create machine to machine type of client that we will use to periodically import some data from our external service into our DB via REST API. So, in this case, there is no concept of user, request from external service is general and not user related.
We can configure various things and also select one of the API scopes which are allowed to be invoked from this client. Auth0 will automatically select OAuth and Client Credentials grant for this client type and we will get ID and Secret.
- The Application authenticates with the Authorization Server using its Client ID and Client Secret.
- The Authorization Server validates this information and returns an Access Token.
- The Application can use the Access Token to call the Resource Server on behalf of itself.
Client can use received token until it expires and after that can just repeat the authorization procedure.
Our backend, using Auth0 libraries, will check for existence and validity of the token, if there is a proper scope and in that case successfully proceed with logic.
As you can see, Auth0 is doing all the hard work for us, we don’t have to think a lot about the strategy or implementation, it gives us the best practices, platform and tools to implement it easy.
Single Page Application
Situation is now more complicated – our web application will call our backend on behalf of a user. Auth0 will select Implicit Grant of OAuth for this type client.
- The app initiates the flow and redirects the browser to Auth0, so the user can authenticate.
- Auth0 authenticates the user. The first time the user goes through this flow, and if the application is a third party application, a consent page will be shown where the permissions, that will be given to the Client, are listed (for example, post messages, list contacts, and so forth).
- Auth0 redirects the user to the app with an Access Token (and optionally an ID Token) in the hash fragment of the URI. The app can now extract the tokens from the hash fragment.
- The app can use the Access Token to call the API on behalf of the user.
Default and suggested way of authentication is, so called, Universal Login where user is redirected to Auth0 page to authenticate. By default this will be on Auth0 domain, but if we use (premium) custom domain it can be something like login.ourdomain.com. This is the same way as Google works, for example, and users are already familiar with this approach. This can also be done in the popup / new tab, if preferred. Other approach is Embedded Login without redirect where everything is in our app, but it’s less secure, more complicated to implement more difficult to maintain (for each client) and not consistent. If we use Universal login we can manage everything in one central place, like social logins, look and feel, etc.
Other things to consider is how to implement UI for login and signup. There are 3 options:
- Lock – Auth0 UI library which handles everything for us. It can be customized to some degree and it’s default in case of Universal login (but can be changed via hosted/custom pages).
- SDK – if we want to control UI fully, we can use Auth0 SDK to communicate with Auth0 and implement custom UI.
- Auth0 API – hardcore approach where we only use Auth0 REST API and implement everything on our own.
I’d always choose this combo – Universal login with custom domain and customized Lock UI. Fast and safe way to do it, everything is centralized, consistent and easy to maintain. Users are used to it and never leave your domain. If you want to have total control of the UI and always stay in the app then I’d choose Embedded login with SDK approach.
When we are done with authentication our web app will have ID token and access token. ID token contains information about permissions that we can set for web app (and that correspond to backend scopes) and could be used to properly display the UI depending on the role/permission of the user. Access token is sent to the backend.
Backend will again check for token, but now can also identify the user from it. We can send additional information with token about the user for this purpose.
So again, we can see how easy it is with Auth0 to get one centralized and secure place for signup/login with social integration, MFA, SSO, etc. We use SDKs and platform provided by Auth0 to make our lives easier.
This is Native scenario (mobile or desktop apps). OAuth Proof Key for Code Exchange (PKCE) is used for this type of client. Everything is almost the same as in SPA case, it’s just that authentication procedure is more complicated:
- The native app initiates the flow and redirects the user to Auth0 sending the
- Auth0 redirects the user to the native app with an
authorization_codein the query string.
- The native app sends the
code_verifiertogether with the
- Auth0 validates this information and returns an Access Token (and optionally a Refresh Token).
- The native app can use the Access Token to call the API on behalf of the user.
There are other scenarios like SSO for regular web apps or maybe if we want to open API publicly, dynamic client registration could be used. There are so many options.
Information about users is stored by default in Auth0 database. This can be changed to keep info in our own cloud, infrastructure or DB, but I’d suggest to keep them on their side to keep everything as simple as possible.
It is possible to extend information about the user, so we could keep additional info on their side also. Better approach, though, would be to create corresponding user structures on our backend side with any additional information about the user that are business specific and just to reference Auth0 user (we can do that by Auth0 ID from access token).
Good strategy should be made for this.
I like the idea of outsourcing auth logic to Auth0 and focus myself on the business logic! 🙂