Callum Slater

Callum Slater

1559633331

Stateless Authentication with JSON Web Tokens

Stateless Authentication with JSON Web Tokens: Learn how to protect your microservice, API, or web app using JSON Web Tokens to create a stateless authentication protocol.

Whether you’re writing a public API or an internal microservice, getting authentication right can make or break your API. Let’s take a look at a JSON Web Token-based authentication system.

We’ll begin with basic authentication & JWT concepts, followed by a detailed walkthrough of designing an authentication service with plenty of code examples.

Before we begin, some definitions are in order:

  • Credential: a fact that describes an identity
  • Authentication: Validation of a credential to identify an entity
  • Authorization: Verification that an entity is allowed to access a resource or perform an action

What are JSON Web Tokens?

JSON Web Tokens (JWT - pronounced “jot”) are a compact and self-contained way for securely transmitting information and represent claims between parties as a JSON object.

This is an encoded JSON Web Token:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1MWQ4NGFjMS1kYjMxLTRjM2ItOTQwOS1lNjMwZWJiYjgzZGYiLCJ1c2VybmFtZSI6Imh1bnRlcjIiLCJzY29wZXMiOlsicmVwbzpyZWFkIiwiZ2lzdDp3cml0ZSJdLCJpc3MiOiIxNDUyMzQzMzcyIiwiZXhwIjoiMTQ1MjM0OTM3MiJ9.cS5KkPxtEJ9eonvsGvJBZFIamDnJA7gSz3HZBWv6S1Q 

JSON Web Tokens such as the one shown is a string consisting of three components, each component delimited by a . (period) character.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJqdGkiOiI1MWQ4NGFjMS1kYjMxLTRjM2ItOTQwOS1lNjMwZWJiYjgzZGYiLCJ1c2VybmFtZSI6Imh1bnRlcjIiLCJzY29wZXMiOlsicmVwbzpyZWFkIiwiZ2lzdDp3cml0ZSJdLCJpc3MiOiIxNDUyMzQzMzcyIiwiZXhwIjoiMTQ1MjM0OTM3MiJ9
.
cS5KkPxtEJ9eonvsGvJBZFIamDnJA7gSz3HZBWv6S1Q

Base64Url decoding a JSON Web Token gives us the following:

{
  "alg": "HS256",
  "typ": "JWT"
}
.
{
  "jti": "51d84ac1-db31-4c3b-9409-e630ebbb83df",
  "username": "hunter2",
  "scopes": ["repo:read", "gist:write"],
  "iss": "1452343372",
  "exp": "1452349372"
}
.
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

JSON Web Tokens consists of the following three components: the Header, Payload, and Signature. A token is constructed as follows:

  1. You generate a claim of arbitrary JSON data (the Payload), which in our case contains all the required information about a user for the purposes of authentication. A Header typically defines the signing algorithm alg and type of token typ.
  2. You decorate it with some metadata, such as when the claim expires, who the audience is, etc. These are known as claims, defined in the JWT IETF Draft.
  3. The data (both Header and Payload) is then cryptographically signed with a Hash-based Message Authentication Code (HMAC) secret. This Signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message was’t changed in the way.
  4. The Header, Payload, and Signature are then Base64 encoded and concatenated together with periods to delimit the fields, which results in the token we see in the first example.

JWTs can also be signed using a secret (with HMAC algorithm) OR a public/private key pair using RSA.

For authentication purposes, a JWT serves as the credential/identity object that clients must show to gatekeepers to verify that you’re allowed access protected resources you want to access. It can be signed by a trusted party, and verified by gatekeepers.

JSON Web Tokens work across different programming languages. You should be able to find clients you can use to sign and verify tokens written for your stack.

Authentication Flow

One of the primary use cases of using JWTs is to authenticate requests. Once a user is logged in, each subsequent request can include the JWT to access previously inaccessible protected resources and services.

To illustrate, let’s imagine an authentication layer for a set of microservices containing a user’s protected resource.

Our authentication flow happens between the following parties:

  • Resource Owner (the User): the party that owns the resource to be shared. Let’s call our user Tom.
  • Resource Server: the service that holds the protected resource. Our WalletService holds the Wallet resource, which is a user’s digital wallet.
  • Authorization Server: the service that verifies the identity of users. Let’s call this AuthService.
  • Client: the application (web/mobile/others) that makes requests to the Resource Server on behalf of the Resource Owner. Let’s have a WalletApp Android app.

If you’re familiar with OAuth2, our flow is similar to the Resource Owner Password Credentials Grant flow. Depending on your use case, other flows may be a better fit for your application.

Our entire flow goes as follows:

  1. Tom the Resource Owner wants to view the contents of his digital wallet through the Client.
  2. The Client talks to WalletService, requesting for Tom’s Wallet resource.
  3. Unfortunately, Wallets are a protected resource. Clients will need to pass an access token to continue.
  4. The Client talks to AuthService, requesting an access token. AuthService responds by asking for the user’s credentials.
  5. The Client redirects Tom the Resource Owner to the AuthService, which gives Tom the option to either deny or accept the Client’s request for access.
  6. AuthService verifies Tom’s credentials, redirects her back to the Client, and grants an Authorization Code to the Client.
  7. The Client presents the authorization code to the AuthService, returning an access token (a JWT) to the Client if successful.
  8. WalletApp presents the access token to the WalletService, requesting for Tom’s Wallet resource. Whenever the client wants to access a protected route or resource, it should send the JWT, typically in the Authorization header using the Bearer schema e.g. Authorization: Bearer
  9. WalletService validates the token, decoding the JWT, and parsing its contents.
  10. (Optional, see Revoking Tokens) WalletService asks AuthService to validate the token.
  11. If the access token is valid for the requested operation and resource, WalletService returns Tom’s Wallet to the WalletApp Client.
  12. WalletApp shows Tom his Wallet.

Note that the Resource Owner does not share their credentials to the Client directly. Instead, users notify the Authorizer that the Client may access whatever it is that they requested, and the Client authenticates separately with an authorization code. For more details, check out the OpenID Connect spec.

In this article, we’re focusing primarily on step 8 to 12.

A Minimum Viable Authentication Service

Let’s work on an authentication service for the flow above using plain old Node + Express. Of course, you’re free to use whatever you’d like for your own authentication service.

We need at minimum a single endpoint:

Stateless Authentication with JSON Web Tokens

// Authentication Service API Login endpoint

var _ = require('underscore');
var Promise = require('bluebird');
var express = require('express');
var router = express.Router();

var models = require('../models');
var User = models.User;
var JWT = require('../utils/jwt');

// Login
router.post('/sessions', function(req, res, next) {
  var params = _.pick(req.body, 'username', 'password', 'deviceId');
  if (!params.username || !params.password || !params.deviceId) {
    return res.status(400).send({error: 'username, password, and deviceId ' +
                                'are required parameters'});
  }

  var user = User.findOne({where: {username: params.username}});
  var passwordMatch = user.then(function(userResult) {
    if (_.isNull(userResult)) {
      return res.status(404).send({error: 'User does not exist'});
    }
    return userResult.comparePassword(params.password);
  });

  Promise.join(user, passwordMatch, function(userResult, passwordMatchResult) {
    if (!passwordMatchResult) {
      return res.status(403).send({
        error: 'Incorrect password'
      });
    }

      var userKey = uuid.v4();
      var issuedAt = new Date().getTime();
      var expiresAt = issuedAt + (EXPIRATION_TIME * 1000);

      var token = JWT.generate(user.username, params.deviceId, userKey, issuedAt, expiresAt);

      return res.status(200).send({
            accessToken: token;
      });
  })
    .catch(function(error) {
      console.log(error);
      next(error);
    });
});
//lib/utils/jwt.js

var _ = require('underscore');
var config = require('nconf');
var jsrsasign = require('jsrsasign');

var sessionKey = require('../utils/sessionKey');
var JWT_ENCODING_ALGORITHM = config.get('jwt:algorithm');
var JWT_SECRET_SEPARATOR = config.get('jwt:secret_separator');

function JWT() {
  this.secretKey = config.get('jwt:secret');
}

// Generate a new JWT
JWT.prototype.generate = function(user, deviceId, userKey, issuedAt,
                                  expiresAt) {
  if (!user.id || !user.username) {
    throw new Error('user.id and user.username are required parameters');
  }

  var header = {
    alg: JWT_ENCODING_ALGORITHM, typ: 'JWT'
  };
  var payload = {
    username: user.username,
    deviceId: deviceId,
    jti: sessionKey(user.id, deviceId, issuedAt),
    iat: issuedAt,
    exp: expiresAt
  };
  var secret = this.secret(userKey);
  var token = jsrsasign.jws.JWS.sign(JWT_ENCODING_ALGORITHM,
                         JSON.stringify(header),
                         JSON.stringify(payload),
                         secret);
  return token;
};

// Token Secret generation
JWT.prototype.secret = function(userKey) {
  return this.secretKey + JWT_SECRET_SEPARATOR + userKey;
};

module.exports = new JWT();

Great! We can now return access tokens upon succesful login. In the next sections, we’ll take a look at introducing additional capabilities for our authentication system as well as writing an authentication middleware that we can easily use to protect the routes of future microservices.

But first, let’s learn more about the reasons why we use JWTs instead of regular plaintext tokens.

Benefits of Using JWTs for Authentication

Using a JSON Web Token as your identity object gives you a handful of advantages compared to an opaque OAuth2 Bearer token:

1. Fine Grained Access Control: You can specify detailed access control information within the token itself as part of its payload. In the same way that you can create AWS security policies with very specific permissions, you can limit the token to only give read/write access to a single resource. In contrast, API Keys tend to have a coarse all-or-nothing access.

[Stateless Authentication with JSON Web Tokens

You can populate your tokens with private claims containing a dynamic set of scopes with JWTs. For example:

{
  "jti": "51d84ac1-db31-4c3b-9409-e630ebbb83df",
  "username": "hunter2",
  "scopes": ["repo:read", "gist:write"],
  "iss": "1452343372",
  "exp": "1452349372"
}

Your authentication middleware can parse this JWT metadata and perform validation without making a request to the authorization server. The API endpoint would simply check for the presence of the right scope atribute as follows.

We’ve covered this in the previous section, alongside code examples.

2. Introspectable: A JSON Web Token carries a header-like metadata that can be easily inspected for client-side validation purposes, unlike plaintext Bearer OAuth tokens which we can’t decode and inspect without making calls to our database.

3. Expirable: JSON Web Tokens can have built-in expiry mechanisms through the exp property. The exp (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.

4. Stateless: All the information needed to complete a particular request is sent along with it, including an Authorization HTTP header which contains our JWT which serves as an ‘identity object.’ Since the payload contains all the required information for us to authenticate the user, we can avoid making repeated calls to our database.

5. Encrypted: While a JWT’s signature prevents malicious parties from tampering with it, the token’s header is only Base64 encoded. When dealing with confidential identifiers in your tokens, you should encrypt your tokens using AES.

At this point you might be thinking:

“Wow, that’s great! I can implement my authentication entirely stateless without having to store any session information!”

The above is true in that you can perform client side validation on the exp expiry time claim to invalidate an expired token.

However, we notice a few issues that our current design have not addressed:

What happens when you want to log a user out of an application? Say you updated the schema of your tokens. How do you handle the old tokens that still haven’t expired? When you deploy this update to the application, how do you invalidate the current sessions? When you’re storing sessions?

At this point, we don’t have a way for our authorization server to invalidate a session that has not yet expired.

Revoking Tokens

One issue with a purely stateless approach is we have no way to revoke/invalidate issued tokens before they expire. In other words, we can’t manually log out a user. If a malicious party manages to acquire a token and we KNOW that a malicious party has the token, we’d be sitting ducks. We have no way to take away access for already issued tokens.

We could have client-side logic that clears any expired session tokens during validation. However, client-side security is insufficient. To help prevent token misuse, we need the ability to revoke tokens that have already been issued.

There’s the chance that malicious parties can see your services’ request headers. Tou should use TLS for client-server and intra-service communication to ensure that nobody sniffs your network requests. Having said that, we want our authentication system to be safe even if an attacker can intercept the network communication between the client and the server.

Depending on your use case, there are two approaches we can take to support two different token invalidation capabilities. Both approaches require the use of additional storage such as Redis for storing some form of a token’s identifier.

Redis is a wonderful key-value storage and can be extremely useful to save ephemeral data such as our tokens. It includes features like automatic deletion or expiration for tokens, can handle lots of writes, and is horizontally scalable.

Both approaches also require our validation middleware to make requests to the authorization server for token verification. Let’s take a look at how we can implement them:

1. To be able to revoke all tokens belonging to a single user, we can simply sign JWTs belonging to that user with her very own private secret. You can dynamically generate these secrets or you can use a hash of their password.

Then, during our token validation process, we can retrieve this private secret from a DB/service (in our case from KeyService) to verify the token’s signature.

Revoking the token can be done by changing or deleting that user’s secret, thus invalidating all issued tokens belonging that that user.

2. To be able to revoke an individual token, where users can have multiple tokens on different devices, will require us to generate a unique jti identifier for each JWT, which we can use as an identifier in KeyService for retrieving a dynamically generated, session-specific secret created for the purposes of signing and verifying a single token.

  // Verify JWT
  KeyService.get(payload.jti)
    .then(function(userKey) {
      var authenticated = JWT.verify(token, userKey);
      if (authenticated) {
        return next();
      }

      return next(new Error('403 Invalid Access Token'));
    });

The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well. One approach that can help minimize collisions is to use uuids instead of integers as your identifier.

For both approaches, we also need to prevent replay attacks by including unique identifiers in the jti and timestamps in the iat (issued at) claim as part of your JWT payload. This ensures that each token generated is unique.

We need to add additional endpoints:

Stateless Authentication with JSON Web Tokens

The GET endpoint will be primarily used by our authentication middleware to retrieve the secret used to sign the JWT and verify if the signature is valid.

The DELETE endpoint will either change or remove the secret used for the user’s session at a particular device so that the JWT signature verification fails and a 403 Forbidden response is triggered.

We also create a service wrapper for storing user/session-specific secrets used to sign JWTs, with methods get, set, and delete:

// KeyService.js, a key storage backed by Redis

// KeyService stores and manages user-specific keys used to sign JWTs
var redis = require('redis');
var Promise = require('bluebird');
var config = require('nconf');
var uuid = require('node-uuid');

var JWT = require('../utils/jwt');
var EXPIRATION_TIME = config.get('key_service:expires_seconds');
var sessionKey = require('../utils/sessionKey');
Promise.promisifyAll(redis.RedisClient.prototype);

function KeyService() {
  this.client = redis.createClient(config.get('key_service:port'),
                                   config.get('key_service:host'));
  this.client.on('connect', function() {
    console.log('Redis connected.');
  });
  console.log('Connecting to Redis...');
}

// Retrieve a JWT user key
KeyService.prototype.get = function(sessionKey) {
  return this.client.getAsync(sessionKey);
};

// Generate and store a new JWT user key
KeyService.prototype.set = function(user, deviceId) {
  var userKey = uuid.v4();
  var issuedAt = new Date().getTime();
  var expiresAt = issuedAt + (EXPIRATION_TIME * 1000);

  var token = JWT.generate(user, deviceId, userKey, issuedAt, expiresAt);
  var key = sessionKey(user.id, deviceId, issuedAt);

  var setKey = this.client.setAsync(key, userKey);
  var setExpiration = setKey.then(this.client.expireAsync(key,
                                  EXPIRATION_TIME));
  var getToken = setExpiration.then(function() {
    return token;
  });

  return getToken;
};

// Manually remove a JWT user key
KeyService.prototype.delete = function(sessionKey) {
  return this.client.delAsync(sessionKey);
};

module.exports = new KeyService();

Note that an expiry mechanism is built in, which utilizes Redis’ [EXPIRE](https://redis.io/commands/expire) feature to automatically remove sessions that have expired, thereby invalidating any issued tokens signed with that secret.

Here is our main router, updated to handle the additional endpoints and talk to KeyService:

// Authentication Service API endpoints

var _ = require('underscore');
var Promise = require('bluebird');
var express = require('express');
var router = express.Router();

var models = require('../models');
var User = models.User;
var KeyService = require('../services/KeyService');
var ErrorMessage = require('../utils/error');

// Register
router.post('/users', function(req, res, next) {
  var params = _.pick(req.body, 'username', 'password');
  if (!params.username || !params.password) {
    return res.status(400).send({error: 'username and password ' +
                                'are required parameters'});
  }

  User.findOrCreate({
    where: {username: params.username},
    defaults: {password: params.password}
  })
  .spread(function(user, created) {
    if (!created) {
      return res.status(409).send({error: 'User with that username ' +
                                  'already exists.'});
    }
    res.status(201).send(user);
  })
  .catch(function(error) {
    res.status(400).send(ErrorMessage(error));
  });
});

// Login
router.post('/sessions', function(req, res, next) {
  var params = _.pick(req.body, 'username', 'password', 'deviceId');
  if (!params.username || !params.password || !params.deviceId) {
    return res.status(400).send({error: 'username, password, and deviceId ' +
                                'are required parameters'});
  }

  var user = User.findOne({where: {username: params.username}});
  var passwordMatch = user.then(function(userResult) {
    if (_.isNull(userResult)) {
      return res.status(404).send({error: 'User does not exist'});
    }
    return userResult.comparePassword(params.password);
  });

  Promise.join(user, passwordMatch, function(userResult, passwordMatchResult) {
    if (!passwordMatchResult) {
      return res.status(403).send({
        error: 'Incorrect password'
      });
    }

    return KeyService.set(userResult, params.deviceId)
        .then(function(token) {
          res.status(200).send({
            accessToken: token
          });
        });
  })
    .catch(function(error) {
      console.log(error);
      next(error);
    });
});

// Get Session
router.get('/sessions/:sessionKey', function(req, res, next) {
  var sessionKey = req.params.sessionKey;
  if (!sessionKey) {
    return res.status(400).send({error: 'sessionKey is a required parameters'});
  }

  KeyService.get(sessionKey)
    .then(function(result) {
      if (_.isNull(result)) {
        return res.status(404).send({error: 'Session does not exist or has ' +
                                    'expired. Please sign in to continue.'});
      }
      res.status(200).send({userKey: result});
    })
    .catch(function(error) {
      console.log(error);
      next(error);
    });
});

// Logout
router.delete('/sessions/:sessionKey', function(req, res, next) {
  var sessionKey = req.params.sessionKey;
  if (!sessionKey) {
    return res.status(400).send({error: 'sessionKey is a required parameter'});
  }

  KeyService.delete(sessionKey)
    .then(function(result) {
      if (!result) {
        return res.status(404).send();
      }
      res.status(204).send();
    })
    .catch(function(error) {
      console.log(error);
      next(error);
    });
});

module.exports = router;

Updated Authentication Flow

Below is our updated flow with support for revoking already issued tokens:

Stateless Authentication with JSON Web Tokens

We introduce some additional steps in our token validation process (this happens in our middleware) that communicates with an external private secret storage KeyService to retrieve the secrets necessary for decoding and verifying the JWT signature.

As we’ve talked about, this allows us to introduce the ability to expire and manually revoke already issued tokens at the cost of some complexity.

A Minimum Viable Authentication Middleware

Alongside our AuthService, we can and should write a companion Node.js module that other developers can use to easily add authentication to their microservices. For example:

var auth = require('auth');
router.post('/protected', auth.isAuthenticated, function(req, res, next) {
  res.status(200).send();
});

FYI, the isAuthenticated middleware checks that the Authorization: Bearer headers in each incoming request to that route is valid. The source code is supplied below.

You can also protect ALL routes like so:

var auth = require('auth');
app.use(auth.isAuthenticated);

The isAuthenticated middleware can be written as follows:

// index.js

var base64url = require('base64url');
var JWT = require('./lib/utils/jwt');
var KeyService = require('./lib/services/KeyService');

function isAuthenticated(req, res, next) {
  // Guard clauses
  var authorization = req.headers.authorization;
  if (!authorization || !(authorization.search('Bearer ') === 0)) {
    return next(new Error('401 Missing Authorization Header'));
  }
  var token = authorization.split(' ')[1];
  if (!token) {
    return next(new Error('401 Missing Bearer Token'));
  }

  // Unpack JWT
  var components = token.split('.');
  var header = JSON.parse(base64url.decode(components[0]));
  var payload = JSON.parse(base64url.decode(components[1]));
  var signature = components[2];

  // Verify JWT
  KeyService.get(payload.jti)
    .then(function(userKey) {
      var authenticated = JWT.verify(token, userKey);
      if (authenticated) {
        return next();
      }

      return next(new Error('403 Invalid Access Token'));
    });
}

module.exports = {
  isAuthenticated: isAuthenticated
};

KeyService is a wrapper over the Redis storage used to store session-specific user keys, indexed by a uuid identifier contained in the token’s jti claim. We’ve seen this before, except the operations defined for our middleware is strictly read-only.

// KeyService stores and manages user-specific keys used to sign JWTs
var redis = require('redis');
var Promise = require('bluebird');
var config = require('nconf');

Promise.promisifyAll(redis.RedisClient.prototype);

function KeyService() {
  this.client = redis.createClient(config.get('key_service:port'),
                                   config.get('key_service:host'));
  this.client.on('connect', function() {
    console.log('Redis connected.');
  });
  console.log('Connecting to Redis...');
}

// Retrieve a JWT user key
KeyService.prototype.get = function(sessionKey) {
  return this.client.getAsync(sessionKey);
};

module.exports = new KeyService();

JWT is a lightweight wrapper of the jsrsasign crypto library. We use the jsrsassign crypto library to verify our JWTs:

Be careful when choosing which crypto library you use to sign and verify JWTs. Be sure to check jwt.io for any security vulnerabilities.

// lib/utils/jwt.js

var _ = require('underscore');
var config = require('nconf');
var jsrsasign = require('jsrsasign');
var base64url = require('base64url');

var JWT_ENCODING_ALGORITHM = config.get('jwt:algorithm');
var JWT_SECRET_SEPARATOR = config.get('jwt:secret_separator');

function JWT() {
  this.secretKey = config.get('jwt:secret');
}

JWT.prototype.verify = function(token, userKey) {
  var secret = this.secret(userKey);
  var isValid = jsrsasign.jws.JWS.verifyJWT(token,
                                            secret,
                                            {
                                              alg: [JWT_ENCODING_ALGORITHM],
                                              verifyAt: new Date().getTime()});
  return isValid;
};

JWT.prototype.secret = function(userKey) {
  return this.secretKey + JWT_SECRET_SEPARATOR + userKey;
};

module.exports = new JWT();

Q: Why are we using both a global secret alongside the user-specific secret when computing secret?

A: Having a global secret lets us easily invalidate ALL tokens belonging to ALL users by simply changing this single secret value, thus invaliding the JWT signatures of all already issued tokens.

Writing modules for cross-cutting concerns such as authentication in this way lets you save development time and effort on future microservices. You can quickly bootstrap new services with an increasingly rich set of capabilities as you write more and more reusable modules. Shared modules also helps keep behaviour consistent across all your different services.

Other JWT Use Cases

JSON Web Tokens can securely transmit information between parties, since its signature lets us be sure that its senders are who we expect. Other use cases involving JWTs include as tokens within reset password links. We can use JWTs to create signed hyperlinks without needing to store password reset tokens in a database.

In Closing

I’ve presented one approach to building an authentication layer using JSON Web tokens. We’ve also gone through a number of the design decisions to help prevent some security loopholes.

While JWTs may seem like a fairly sane method of authentication it’s important for us to not ignore the lessons we’ve learned from older authentication schemes with years of combat experience.

Through this process, I hope I’ve shared with you how client-side authentication schemes using JWTs has its own risks and limitations which needs to be investigated throughly before going into implementation.

Let me know what you think in the comments below!

#json #node-js #javascript #security #web-development

What is GEEK

Buddha Community

Stateless Authentication with JSON Web Tokens

How To Set Up Two-Factor Authentication in cPanel

What is 2FA
Two-Factor Authentication (or 2FA as it often referred to) is an extra layer of security that is used to provide users an additional level of protection when securing access to an account.
Employing a 2FA mechanism is a vast improvement in security over the Singe-Factor Authentication method of simply employing a username and password. Using this method, accounts that have 2FA enabled, require the user to enter a one-time passcode that is generated by an external application. The 2FA passcode (usually a six-digit number) is required to be input into the passcode field before access is granted. The 2FA input is usually required directly after the username and password are entered by the client.

#tutorials #2fa #access #account security #authentication #authentication method #authentication token #cli #command line #cpanel #feature manager #google authenticator #one time password #otp #otp authentication #passcode #password #passwords #qr code #security #security code #security policy #security practices #single factor authentication #time-based one-time password #totp #two factor authentication #whm

Hollie  Ratke

Hollie Ratke

1598004000

Knock knock, who’s there? Authenticating your single page apps using JSON Web Tokens

accessible for deaf/hearing-impaired: sign language interpreter (DGS) visible for complete duration + captions // slide collection https://buff.ly/2YLcPlA
// License: CC BY-ND https://buff.ly/2TN3XIo

In this talk, I will try to explain in depth, the way JSON Web Tokens work and can be used to secure your single page apps. I will explain the difference between using opaque tokens and JWTs. The talks will also give an overview of a modern authentication flow and a step by step breakdown of how it works exactly. No specific previous knowledge is required, but it helps the audience has some experience with authenticating users.

What are the key takeaways from this talk?
Authentication does not have to be over complicated, as long as you use the right solution for each situation.

#coding #json #authenticating #json web

Brandon  Adams

Brandon Adams

1625637060

What is JSON? | JSON Objects and JSON Arrays | Working with JSONs Tutorial

In this video, we work with JSONs, which are a common data format for most web services (i.e. APIs). Thank you for watching and happy coding!

Need some new tech gadgets or a new charger? Buy from my Amazon Storefront https://www.amazon.com/shop/blondiebytes

What is an API?
https://youtu.be/T74OdSCBJfw

JSON Google Extension
https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa?hl=en

Endpoint Example
http://maps.googleapis.com/maps/api/geocode/json?address=13+East+60th+Street+New+York,+NY

Check out my courses on LinkedIn Learning!
REFERRAL CODE: https://linkedin-learning.pxf.io/blondiebytes
https://www.linkedin.com/learning/instructors/kathryn-hodge

Support me on Patreon!
https://www.patreon.com/blondiebytes

Check out my Python Basics course on Highbrow!
https://gohighbrow.com/portfolio/python-basics/

Check out behind-the-scenes and more tech tips on my Instagram!
https://instagram.com/blondiebytes/

Free HACKATHON MODE playlist:
https://open.spotify.com/user/12124758083/playlist/6cuse5033woPHT2wf9NdDa?si=VFe9mYuGSP6SUoj8JBYuwg

MY FAVORITE THINGS:
Stitch Fix Invite Code: https://www.stitchfix.com/referral/10013108?sod=w&som=c
FabFitFun Invite Code: http://xo.fff.me/h9-GH
Uber Invite Code: kathrynh1277ue
Postmates Invite Code: 7373F
SoulCycle Invite Code: https://www.soul-cycle.com/r/WY3DlxF0/
Rent The Runway: https://rtr.app.link/e/rfHlXRUZuO

Want to BINGE?? Check out these playlists…

Quick Code Tutorials: https://www.youtube.com/watch?v=4K4QhIAfGKY&index=1&list=PLcLMSci1ZoPu9ryGJvDDuunVMjwKhDpkB

Command Line: https://www.youtube.com/watch?v=Jm8-UFf8IMg&index=1&list=PLcLMSci1ZoPvbvAIn_tuSzMgF1c7VVJ6e

30 Days of Code: https://www.youtube.com/watch?v=K5WxmFfIWbo&index=2&list=PLcLMSci1ZoPs6jV0O3LBJwChjRon3lE1F

Intermediate Web Dev Tutorials: https://www.youtube.com/watch?v=LFa9fnQGb3g&index=1&list=PLcLMSci1ZoPubx8doMzttR2ROIl4uzQbK

GitHub | https://github.com/blondiebytes

Twitter | https://twitter.com/blondiebytes

LinkedIn | https://www.linkedin.com/in/blondiebytes

#jsons #json arrays #json objects #what is json #jsons tutorial #blondiebytes

Giles  Goodwin

Giles Goodwin

1600094940

JWT (JSON Web Tokens) User Authentication in Next.js Web Application

JWT (JSON Web Tokens) implement information with encoded token between client and server. JWT can be use in any programming language platform for many developers in their projects. Visit this website to view a better understanding of JWT tokens.

Image for post

JWT (JSON Web Tokens) logo.

_JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties. — _https://jwt.io/

Simple flow of JWT

Simple flow of JWT

Next.js feature has an awesome API that can allow you to use request and response within client and server communication. Below is the example of request and response in ./pages/api/hello.js from a default Next.js project template.

export default (req, res) => {
   res.statusCode = 200
   res.json({ name: 'John Doe' })
}

#nextjs #authentication #javascript #react #jwt-token #json

Hollie  Ratke

Hollie Ratke

1596830400

What is JSON Web Token

A JSON Web Token (JWT) is a JSON object that is defined in RFC 7519 as a safe way of transmitting information between two parties. Information in the JWT is digitally-signed, so that it can be verified and trusted.

JWT Properties

  • Less verbose - JWT is compact in size and can be passed in the URL, POST parameter, or HTTP header.
  • Self-contained - JWT carries all of information needed for exchanging information and authentication.
  • Versatile - JWT works in .NET, Python, Node.js, Java, PHP, Ruby, Go, JavaScript, and Haskell.

JWT Use Cases

  • Information Exchange - JWT can be used between two parties to exchange information. JWT is digitally-signed and can be used in a secure public/private key pair. Information is verified using the public key on the other end.
  • Authentication - JWT can contain user information in the payload and can be used in the session to authenticate the user. Once authenticated, users can access protected resources in an application using the JWT included in the request. So, every request will be authenticated by verifying the JWT.

JWT contains three parts: Header, Payload, and Signature which are separated by a dot.

Header.Payload.Signature

Header

The JWT Header consists of 2 parts:

  • The token type (typ): JWT
  • Algorithm used to sign the token (alg)
{  
 "typ" : "JWT",  
 "alg" : "HS256"  
}

Header Algorithm Types:

  • Symmetric Algorithms - This algorithm type uses a single secret key to both sign and verify the JWT token. For example: HMAC algorithms.
  • Asymmetric Algorithms - This algorithm type uses a private key to sign the token and a public key to verify the signature. For example: RSA and ECDSA algorithms.

alg Value

Digital Signature or MAC Algorithm

AlgoDescriptionHS256HMAC using SHA-256 hash algorithmHS384HMAC using SHA-384 hash algorithmHS512HMAC using SHA-512 hash algorithmRS256RSASSA using SHA-256 hash algorithmRS384RSASSA using SHA-384 hash algorithmRS512RSASSA using SHA-512 hash algorithmES256ECDSA using P-256 curve and SHA-256 hash algorithmES384ECDSA using P-384 curve and SHA-384 hash algorithmES512ECDSA using P-521 curve and SHA-512 hash algorithm

The Base64Url-encoded Header**,** which is first part of our JWT, looks like the following:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Payload

The Payload, also known as the JWT claim, contains all of the information we want to transmit.

Different types of claims can be used to build the Payload:

  • Registered Claim - These claims are optional but recommended as they contain some metadata about the token:

CodeNameDescriptionississuerIdentifies the principal that issued the JWT.subsubjectIdentifies the principal that is the subject of the JWT.audaudienceIdentifies the recipients that the JWT is intended for.expExpiration timeIdentifies the expiration time on or after which the JWT MUST NOT be accepted for processing.nbfNot beforeIdentifies the time before which the JWT MUST NOT be accepted for processing.iatIssue atIdentifies the time at which the JWT was issued.jtiJWT idUnique identifier for the JWT, can be used to prevent the JWT from being replayed.

  • Public Claim - These claims are defined by you, such as user name, and other important information.
  • Private Claim - A producer and consumer may agree to use claim names that are private. These are subject to collision, so use them with caution.

Example Payload:

{  
 "sub": "1234567890",  
 "name": "Frank Emic",  
 "jti": "4b5fcea6-2a5e-4a9d-97f2-3d8631ea2c5a",  
 "iat": 1521191902,  
 "exp": 1521195630  
}

This example contains a combination of registered and public claims. “sub”,”jti”,”iat”, and “exp” are registered claims and “name” is a public claim.

#json #token #web