Guide: Authorization

Authorization: A Complete Guide

What is Authorization?

Authorization is the process of allowing an entity to have access to something or perform specific actions in a computer system. 

In a multi-user system, the system administrator uses the authorization mechanism to define permissions for each user or group of users. Once a user is logged in, via a process called authentication, the system determines which resources should be available to them during their session. So the term authorization can have two related meanings:

  • Allocation of privileges to users by the system administrator
  • Granting access to users at runtime according to predetermined permissions

In this article:

Authentication vs Authorization

Authentication is the process of verifying a user’s identity—making sure they are who they say they are. Traditionally, the most common method for identity authentication was a password. If the username provided by a user matched the password credentials, the identity was determined valid and the user was granted access.

Passwords are still widely used, but they can be easily compromised and are widely recognized as an ineffective security mechanism. Organizations are transitioning to passwordless authentication, which is more secure and also more convenient for users. It relies on elements like multi-factor authentication (MFA), one-time passwords (OTPs), email verification, and single sign-on (SSO). 

Learn more in our detailed guide to authentication

Authorization comes into action after the user’s identity has been verified through authentication. It provides full or partial access to resources such as devices, files, applications, specific operations or data. To take a simple example: 

  • A user logs into a business application, providing their company username and password. 
  • The application authenticates the user and verifies the password.
  • The application checks what permissions are allocated to that username and grants access to the relevant data and features.

Both authentication and authorization are critical to security. By implementing strong authentication and robust authorization policies, an organization ensures it knows who is accessing its systems and what exactly they have access to. This enables productivity for users, while protecting sensitive assets and meeting the organization’s security and compliance requirements.

Learn more in our detailed guide to authentication vs. authorization

User Authorization Strategies and Techniques

Role-Based Access Control (RBAC)

RBAC mechanisms allow or restrict access to users according to their roles within the organization. It provides users with access to data and applications required to perform their jobs while minimizing the risk of unauthorized activities like access to sensitive data. 

Organizations can use RBAC to define how each user can interact with data. For example, it lets you allow read/write or read-only access to specific roles to limit a user’s ability to perform unauthorized actions, such as data deletion and commands execution.

RBAC use cases

Enterprises use role-based access control to provision privileges according to granular levels of access defined according to employee roles and responsibilities. This method helps protect sensitive data by ensuring employees can access only the information required for their job and perform only actions necessary to carry out their tasks.

Organizations typically assign a role-based access control role to each employee. This role defines a set of permissions for the user. You can create roles such as administrator, specialist, and end-users, limiting access per role to certain tasks and resources.

Learn more in our detailed guide to RBAC

Attribute-Based Access Control (ABAC)

ABAC lets you define access and privileges based on attributes (or characteristics) instead of roles. It helps protect objects such as network devices, IT resources, and data from unauthorized actions and users that do not have the approved characteristics defined by the organization’s security policies.

ABAC evolved from simple access control lists to a form of logical access control. It was initially endorsed in 2011 by the Federal Chief Information Officers Council to help federal organizations improve access control architectures. The council recommended ABAC to help organizations safely share information.

Learn more in our detailed guide to ABAC

Relationship-Based Access Control (ReBAC)

ReBAC applies access decisions according to the relationships between subjects such as users, applications, and devices. When a subject requests access to a resource, the ReBAC mechanism grants or denies access according to the relationships the subject has. 

ReBAC does not allow access based on a certain role (like RBAC) or attributes (like ABAC). Instead, it allows access based on a subject’s relationships with other entities. These relationships influence how the authorization policy grants or denies access to protected resources.

Social networks use ReBAC to allow access. Facebook, for example, allows friends of friends to access photos and posts. It means friends can see the user’s posts and also the friends of these friends. However, this is where it stops—third connections are not allowed access. 

JSON Web Token (JWT)

JSON Web Token (JWT) is an open standard that defines how to securely transmit information between parties like JSON objects. It verifies information by digitally signing it. JWTs are compact and self-contained. You can sign JWTs using a public/private key pair through RSA or ECDSA, or a secret through the HMAC algorithm. 

You can also encrypt JWTs to increase security. Signed tokens can verify claims’ integrity, and encrypted tokens hide claims from other parties. When you use public/private key pairs to sign tokens, the signature certifies that only the party that holds the private key signed it.

You can use JWT for authorization mechanisms. After the user logs in, each subsequent request includes the JWT to allow the user to access the services, resources, and routes permitted with this token. Since JWT can easily be used for different domains and has a small overhead, it also powers many Single Sign-On (SSO) mechanisms.

Related content: Read our guide to JWT authorization

Application Authorization Frameworks

Django Authorization

Django provides a Python web framework for quick development and clean design. Django authentication includes authentication and authorization. Since these features are somewhat coupled, this mechanism works as an authentication system.

Here are the core components of Django authentication:

  • User—these objects serve as the foundation of the authentication system, usually representing the people interacting with the website. You can use objects to restrict access, register user profiles, and associate content with creators. 
  • authenticate()—you can use this component to verify a set of credentials. It takes credentials as keyword arguments, passwords, and usernames for the default case and checks them against each authentication back-end. Lastly, if the credentials are valid for a back-end, it returns a user object.

Django includes a built-in permissions system that lets you assign permissions to specific users as well as groups of users.

Related content: Read our guide to Django authorization (coming soon)

ASP.NET Authorization

ASP.NET Core is an open source framework that you can use to build cloud-enabled Internet-connected applications. It offers high performance for modern, cross-platform design.

ASP.NET Core defines authorization as a simple, declarative role enforced by a policy-based model. It lets you express authorization in requirements while handlers evaluate each user’s claim against these requirements. You can base imperative checks on simple policies or policies that evaluate the user’s identity and the requested resource’s properties.

Related content: Read our guide to ASP.NET authorization (coming soon)

Laravel Authorization

Laravel is an open source framework that offers tools and resources for building modern PHP applications. It provides built-in authentication services and a simple mechanism for authorizing user actions against each resource. It means a user can be authenticated but not authorized to delete or update specific Eloquent models or database records managed by the application. 

Laravel offers two authorizing actions: 

  • Gates—employ a simple, closure-based authorization approach. Ideal for actions unrelated to a specific resource or model, such as viewing an administrator dashboard. 
  • Policies—group logic around a specific resource or model. Ideal for authorizing an action for a specific model or resource.

There is no need to choose between gates and policies—you can include a mix of both options. 

Related content: Read our guide to Laravel authorization (coming soon)

Spring Authorization

Spring is an open source framework that offers infrastructure support for Java applications. You can use it for creating high-performing applications with plain old Java objects (POJOs). Spring Security provides authorization, authentication, and protection against common cyberattacks. It can help you secure imperative as well as reactive applications.

Spring Security provides advanced authorization capabilities that work with various mechanisms. You can use the mechanism provided by Spring Security or integrate with non-Spring Security authentication authorities while using authorization services simply and consistently across your application.

Related content: Read our guide to Spring authorization (coming soon) 

Node.js Authorization

Node.js does not provide built-in authorization, but you can add authorization to your application with readily available libraries. 

There are many ways to achieve authorization in Node.js – let’s see how to do it with the MySQL database and the bcryptjs password hashing library. This is abbreviated from the full tutorial by Manash Kumar Chakrobortty (get the source code here).

Important: The code samples below include raw SQL queries within the code. This is obviously not a good practice and should be avoided at any time. But for the sake of these authorization examples, we use them to demonstrate the functionality.

Step 1: Create routes folder

In your project folder, create a subfolder called routes, with two files:

  • routes/auth.js – this file should define two routes using the router.post() function, one for registration, for example at path /register, and one for login, for example /login.
  • routes/index.js – should import the routes from the auth.js file and define which application path should be mapped to these routes – for example, /api/users.

Step 2: Implement registration

Create a controller to register a new user – this controller should create a user object with fields like username, password, and status, and save it to the database. When receiving the user’s password, use the bcrypt library to securely hash it, like this:

    const salt = await bcrypt.genSalt(10);
    const hasPassword = await bcrypt.hash(req.body.password, salt);

Create a model file to save the user’s data to the database, like this:

User.create = async (newUser) => {
    let insert = await sql.query("INSERT INTO user SET ?", newUser);
    if( insert.insertId ) {
        return insert.insertId;
    }
    else {
        return;
    }
};

Step 3: Implement login

Create a controller that checks if a user exists, and then creates a JSON Web Token (JWT):

const token = jwt.sign({id: user.id, user_type_id: user.user_type_id}, config.TOKEN_SECRET);
res.header("auth-token", token).send({"token": token});

Use bcrypt to compare the user’s provided credentials with the hashed version of the password, like this:

const validPass = await bcrypt.compare(req.body.password, user.password);

Create a model that securely reads the user’s details from the database:

User.login = async (value) => {
    let row = await sql.query(`SELECT * FROM user WHERE mobile = ? OR email = ?`, [value, value]);
    if( row.length ) {
        return row[0];
    }
    else {
        throw new NotFoundError("User does not exist");
    }
};

Step 4: Add authentication and authorization

To add a simple user authentication and authorization mechanism, you can check a JSON web token (JWT) in the header of a request, then allow or deny the request accordingly. 

Warning: This is a simplified implementation, intended for learning purposes, which is not appropriate for a production application.

This code checks for a JWT with a field user_type_id, which can be either 1 for admin or 2 for regular user. 

If a token is absent, the application returns “Access Denied”:

exports.loggedIn = function (req, res, next) {
    let token = req.header('Authorization');
    if (!token) return res.status(401).send("Access Denied");

Otherwise, we check for the value of user_type_id:

try {
        if (token.startsWith('Bearer ')) {
            token = token.slice(7, token.length).trimLeft();
        }
        const verified = jwt.verify(token, config.TOKEN_SECRET); 
        if( verified.user_type_id === 2 ){

If the user is not an admin, we check authorization for the requested URL:

     let req_url = req.baseUrl+req.route.path;
            if(req_url.includes("users/:id") && parseInt(req.params.id) !== verified.id){
                return res.status(401).send("Unauthorized!");
            }
        }
        req.user = verified;
        next();
    }
    catch (err) {
        res.status(400).send("Invalid Token");
    }
}

This function automatically denies access to regular users for any route defined as admin only:

exports.adminOnly = async function (req, res, next) {
    if( req.user.user_type_id === 2 ){
        return res.status(401).send("Access Denied");
    }  
    next();
}

Authorization Best Practices

Design and Implement Authorization Early in the Software Development Lifecycle

Authorization functionality is a critical security component that should be considered during the early phases of the software development lifecycle. Building your application with security in mind helps ensure the design itself is secure, reducing complex and costly fixes when the product is already ready for release. When designing authorization, consider all requirements for roles and privileges and use the most suitable web framework supporting this type of authorization.

Implement Authorization Middleware

Authorization middleware enables you to configure short-lived authorization grants and set up the server to perform continuous authorization on each request. It means the authorization middleware handles the requests, eliminating the risks associated with API endpoints and unprotected URL paths. 

Implement Authorization Policies

Authorization policies enable you to configure and enforce fine-grained access controls. You can use various types of policies, such as mandatory access control (MAC), RBAC, ABAC, or discretionary access control (DAC). 

ABAC is preferable over RBAC, according to the OWASP foundation. However, you should choose the method that suits the application’s requirements, and in some scenarios, ABAC may not be the optimal choice. Ideally, the authorization type should include at least one compulsory deny-by-default policy to block unauthorized access.

Related content: Read our guide to authorization policy (coming soon)

Implement Scope Bounds

A scope bound defines a blast radius for functions and features. It reduces the impact of threats that manage to bypass security controls. Limiting functionality and features to a specific scope can help avoid various vulnerabilities, such as local file inclusion (LFI), remote file inclusion (RFI), and directory traversal. You can implement scope bounds by allowlisting specific local directories, program binaries, and URL endpoints.

Validate and Sanitize Dynamic Values

Validation processes include data verification, and sanitization processes attempt to clean malicious inputs. Proper sanitization and validation of all values that compute authorization, including user inputs, can help prevent the exploitation of many vulnerabilities. Here are key best practices:

  • Validation and sanitization must include user inputs and all session data required to compute authorization. 
  • The sanitization and validation of inputs must be performed on the server side. 

Using input validation and sanitization with scope bounds can help you avoid security risks associated with parameter tampering and vulnerabilities like path traversal, RFI, and LFI.

Implement Authentication and SSO in Internal Applications

Applications should always include access controls. You can use standards like Oauth2, SAML, or OpenID Connect to implement single sign-on (SSO). SSO is an authentication scheme that enables you to defer authentication and authorization policy management to an external identity provider. SSO is considered a standard in application security, but you can use other authentication methods.