📕
TIC
  • Tehnologii ale InformaÅ£iei ÅŸi ComunicaÅ£iilor (TIC)
  • Basic web principles
    • How web pages work
    • The pillars of a web page
    • Extra: Getting Started with GitHub
  • Basic HTML
    • Description and Basic Syntax
    • Extra resources
  • Basic CSS
    • Description and Basic Syntax
    • Advanced Positioning
    • Extra Resources
  • Basic Javascript
    • Description and basic syntax
    • The Document Object Model
    • Extra Resources
    • Basic assignment
    • The Color Game
  • Advanced Javascript
    • Runtime Engine, Callstack, Scope
    • ES6
  • Advanced Javascript 2
  • Programming paradigms
  • OOP Javascript
  • Functional Programming
  • OOP vs. Functional Programming
  • Asynchronous Javascript
  • Backend Javascript
    • NodeJS
    • ExpressJS
    • REST APIs
    • Authentication and Authorization
  • Firebase
    • NoSQL Databases
    • Database as a Service
    • Google Cloud Firestore
    • CRUD operations
    • Securing your database
  • Basic VueJS
  • Agenda: VueJS and Frontend Frameworks
  • Single Page Applications
  • VueJS basic syntax
  • Vue Components
  • Advanced VueJS
  • Advanced apps with Vue CLI
  • Vue Router
  • SPA State Management - Vuex
  • Composition API
  • Evaluation
    • Final Individual assignment
Powered by GitBook
On this page
  • Authentication
  • Authorization
  • Authorizing with JSON Web Token
  • Middleware
  • Basic Auth Example

Was this helpful?

  1. Backend Javascript

Authentication and Authorization

PreviousREST APIsNextNoSQL Databases

Last updated 7 months ago

Was this helpful?

While often used interchangeably, authentication and authorization represent fundamentally different functions.

In simple terms, authentication is the process of verifying who a user is, while authorization is the process of verifying what they have access to.

Authentication

  • Determines whether users are who they claim to be

  • Challenges the user to validate credentials (for example, through passwords, answers to security questions, or facial recognition)

  • Usually done before authorization

  • Generally, transmits info through an ID Token

Authorization

  • Determines what users can and cannot access

  • Verifies whether access is allowed through policies and rules

  • Usually done after successful authentication

  • Generally, transmits info through an Access Token

Authorizing with JSON Web Token

The library has two main functions:

  1. Generate a token, .sign(), This receives multiple arguments.

    1. User identification information - which can be later on decoded

    2. A private key to generate the hash tokens

    3. Options such as Expiration dates

  2. Decode an access token, .verify(). This receives the following arguments:

    1. The access token

    2. The private key to decode it

    3. A callback function that returns an error object, in case the validity of the token fails, and the decoded object.

Middleware

Middleware functions are functions that have access to the request object req, the response object res, and the next function in the application’s request-response cycle. The next function is a function in the Express router that, when invoked, executes the middleware succeeding the current middleware.

You can compose middleware functions using techniques like functional programming. This can make your middleware code more reusable and maintainable.

Middleware functions can perform the following tasks:

  • Execute any code.

  • Make changes to the request and the response objects.

  • End the request-response cycle.

  • Call the next middleware in the stack.

If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.

Middleware functions can be used to perform a variety of tasks, such as:

  • Authentication and authorization: Verify that users are logged in and have the necessary permissions to access certain resources.

  • Logging and error handling: Log requests and handle errors gracefully.

  • Data validation: Ensure that incoming data is valid and meets the application's requirements.

  • Request and response manipulation: Modify the request object or response object before it is sent to the next middleware or route handler.

Basic Auth Example

let secret = 'serverKeptSecret'
const jwt = require('jsonwebtoken') //install from npm


// AUTHENTICATION LOGIC, IF PASSED, DO THE FOLLOWING
//...


// RETURNING THE AUTHORIZATION TOKEN
let tokenEncodedData = {
  email: loginEmail
} //we can encode identification information to use in future authorizations

response.success = true
response.token = jwt.sign(tokenEncodedData, secret, { expiresIn: 3600})
//expiration of the token is optional, if missing, the token won't expire
res.send(response)
//...

// MIDDLEWARE
// checks if the request token exists and has a proper structure
function verifyToken(req, res, next) {
  const bearerHeader = req.headers['authorization']

  if (typeof bearerHeader !== 'undefined') {
    const bearer = bearerHeader.split(' ')
    const bearerToken = bearer[1]
    req.token = bearerToken
    next()
  } else {
    res.sendStatus(401)
  }
}

// SERVING A PRIVATE RESOURCE
app.get('/private', verifyToken, (req, res) => {
// invokes the 'verifyToken' middleware
  jwt.verify(req.token, secret, (err, decoded) => {
  
    if (err) {
      if (err.expiredAt) {
      //if token expired, the err object will have an 'expiredAt' key
        res.send(({message: 'Your token has expired. Please re-authenticate'}))
      } else {
        res.send({message: 'You are NOT authorized to access this resource'})
      }
    } else {
      console.log(decoded.email)
      //we have access to the identification data used to generate the token
      //this way we can write a logic to access only the resources for which
      //a request is authorized
      res.send({message: 'Well kept secret'})
    }
  })
})
//setting global parameters for all HTTP requests
var globalRequestParameters = {    
    mode: 'cors', // no-cors, *cors, same-origin
    cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'same-origin', // include, *same-origin, omit
    headers: {
      'Content-Type': 'application/json'
      // 'Content-Type': 'application/x-www-form-urlencoded',
    },
    redirect: 'follow', // manual, *follow, error
    referrerPolicy: 'no-referrer',
  }
  
  const baseURL = 'http://localhost:3000/'
  
//AUTHENTICATION REQUEST
//...
if (res.success) { //authentication successful
    localStorage.setItem('token', res.token)
    } else {
    console.log('Authentication failed')
    }
//...


// REQUESTING A PRIVATE RESOURCE
function accessPrivateData() {
    let token = localStorage.getItem('token')
    //assuming the authorization token has been stored in localStorage
    if (token) {
        let parameters = { ...globalRequestParameters } //shallow object clone
        parameters.method = 'GET'
        parameters.headers.Authorization = 'Bearer ' + token
        //adding the token to the request
        fetch(baseURL + '/private', parameters)
        .then(res => res.json())
        .then(res => console.log(res)) //logging the private message
        //... optional error handling
    } else {
        console.log('no access token')
    }

}

Other popular AUTH methods.

Session-based Authentication uses server-side sessions to store user data, with a session ID stored in cookies. Compared to JWTs, it's more secure against token theft since sessions can be immediately invalidated, but requires server storage and can be challenging to scale across multiple servers.

API Keys are simple static tokens, often used for service-to-service authentication. They're simpler than JWTs but lack built-in expiration and payload capabilities. While easier to implement, they don't provide claims or user context like JWTs do.

OAuth 2.0 is an authorization framework rather than pure authentication, using access tokens and refresh tokens. Unlike JWTs, it's more complex to implement but provides robust delegation of access rights and better security through short-lived access tokens and separate refresh tokens.

SAML uses XML-based tokens and is common in enterprise environments. Compared to JWTs, SAML tokens are more verbose and complex but provide richer security assertions. They're better suited for enterprise single sign-on but have higher overhead than JWTs.

OpenID Connect builds on OAuth 2.0, adding standardized authentication. It can use JWTs as ID tokens but adds a standardized protocol layer. It's more complex than pure JWT implementation but provides better standardization and security features.

Basic Authentication sends encoded credentials with each request. It's simpler than JWTs but less secure and lacks features like expiration or claims. It's mainly used for simple applications or development environments.

SSO (Single Sign-On) enables one-time login across multiple applications using a central Identity Provider (IdP) like Okta, Azure AD or Google Workspace.

Basic flow:

  1. User visits App A → redirects to IdP

  2. User logs into IdP once

  3. IdP sends signed token back to App A

  4. When user visits App B, IdP sees existing session → auto-login

This works cross-domain through:

  • SAML or OpenID Connect protocols

  • Browser redirects

  • Signed tokens (XML/JWT)

  • IdP session cookies

Key benefits:

  • One login for multiple apps

  • Centralized user management

  • Unified security policies

  • Easy access revocation

  • Audit logging

For our authorization purposes, we'll use an NPM popular library: jsonwebtoken. More information at

More info at

https://www.npmjs.com/package/jsonwebtoken
https://expressjs.com/en/guide/writing-middleware.html#:~:text=The%20next%20function%20is%20a,request%20and%20the%20response%20objects.