One, foreword

Every website, as small as an H5 page, must have a login authentication and authorization module. What are the common authentication and authorization methods? How do you do that? Next, we will explain SSO, OAuth and other related knowledge and apply posture in practice.

Ii. Authentication and Authorization

The terms are often used in combination with each other in terms of security, especially when gaining access to a system. Both are very important topics, often associated with networks as a key part of their service infrastructure. However, the two terms are very different in completely different concepts. Although they are often used in the same context using the same tools, they are completely different from each other.

Authentication means confirming your own identity, while authorization means granting access to the system. Simply put, authentication is the process of verifying your identity, while authorization is the process of verifying that you have access.

You are authorized to use authorization. Authentication is the first step in authorization, and therefore always the first step. Authorization is completed after successful validation.

Example: you want to log in the forum, enter the user name Zhang SAN, password 1234, the password is correct, prove that you are Zhang SAN is zhang SAN, this is authentication; Check user Zhang SAN is a moderator, so he has the authorization to add and delete other posts.

3. Single Sign-on (SSO)

Single Sign On, or SSO for short, is one of the more popular solutions for enterprise business integration. SSO is defined as one login in multiple applications that allows users to access all trusted applications.

For example, QQ Music and Tencent News are two different application systems owned by Tencent. If a user logs in to Tencent News once, he does not need to log in again when he accesses QQ Music, it means that there is a single sign-on between QQ Music and Tencent News.

3.1 the parent domain Cookie

The simplest way to do this is to set the domain property of the Cookie to the parent domain of the current domain, so it is considered a parent domain Cookie. Cookies have a feature that the cookies in the parent domain are shared by the quilt domain. In other words, the cookies in the child domain automatically inherit from the parent domain.

  • System 1:a.zxy.com
  • System 2:b.zxy.com
  • Log in to login.zxy.com
SequenceDiagram System 1->> System 1: Logged in, Login cookie At zxy.com Domain System 2->> System 2: You need to log in to system 2->> Log in to system: Login (with login cookie information) Log in to system ->> Log in to system: Login verification Log in to system ->> System 2: Login succeeded System 2->> System 2: Access resources

3.2 the CAS

Another method is the Central Authentication Service (CAS). For details, see OAuth2.0. The application system checks whether the current request has a Ticket. If the request does not have a Ticket, the user has not logged in to the current system. Because this operation automatically brings the authentication authority’s Cookie, the authentication authority can know whether the user has logged in based on the Cookie. If the authentication center finds that the user has not logged in, the authentication center returns to the login page and waits for the user to log in. If the user has logged in, the authentication center does not allow the user to log in again. Instead, the authentication center generates a Ticket before the login, splices the Ticket behind the target URL, and sends the Ticket to the target application system.

Fourth, the request

4.1 Four ways

OAuth 2.0 defines four types of authorization.

  • Authorization Code
  • Simplified patterns (Implicit)
  • Password mode (Resource owner Password Credentials)
  • Client credentials

4.1.1 Authorization Code Mode

The Authorization Code mode is the most complete authorization mode with the most rigorous procedures. It is characterized by interaction with the authentication server of the “service provider” through the backend server of the client.

sequenceDiagram Resource Owner->>Client: 1. User access Client->>User Agent: 2. The client directs the User to the Authorization Server User Agent->>Authorization Server: 3. Code and Redirect_URI The User selects whether to authorize the client User Agent->>Authorization Server: 5. Authorization Server-->>User Agent: 6. Redirect URL User Agent-->>Client: 7. Redirect URL Client->>Authorization Server: 8. Authorization_code Authorization Server-->>Client: 9. expires_in access_token refresh_token scope

Part of the illustration above is added

  1. Response_type =code&client_id={client ID}&redirect_uri={redirection URI}&scope={permission scope}&state={state}
  2. Redirect URL? code={code}&state={state}
  3. Redirect URL? code={code}&state={state}
  4. grant_type=authorization_code&client_id={client_id}&code={code}&state={state}&redirect_uri={redirect_uri}

4.1.2 Simplified Mode

Implicit Grant Type gets its name as an implicit grant type that asks for tokens directly from an authentication server in the browser, bypassing the “authorization code” step. All steps are done in the browser, the token is visible to the visitor, and the client does not require authentication.

sequenceDiagram Resource Owner->>Client: 1. User access Client->>User Agent: 2. The client directs users to the Authorization Server User Agent->>Authorization Server: 3. Authorize User Agent->>Resource Owner: 4. The User selects whether to authorize the client User Agent->>Authorization Server: 5. Authorization Server-->>User Agent: 6. Token User Agent->>WebHosted Client Resource: 7. The browser issues a request to the Resource server WebHosted Client Resource-->>User Agent: 8. User Agent->>User Agent: 9. Extract token User Agent->>Client: 10. Access_token

Part of the illustration above is added

  1. authorize? Response_type =token&client_id={client ID}&redirect_uri={redirection URI}&scope={permission scope}&state={state}
  2. Expires_in Access_Token refresh_token scope state and contains the access token in the Hash part of the URI

4.1.3 Password Mode

In the Resource Owner Password Credentials Grant mode, users provide their user names and passwords to clients. The client uses this information to request authorization from the “service provider.”

sequenceDiagram Resource Owner->>Client: 1. Username and Password Client->>Authorization Server: Grant_type =password&username={username}&password={password}&scope={permission scope} Authorization Server-->>Client: 3. expires_in access_token refresh_token
  1. Grant_type =password&username={username}&password={password}&scope={permission scope}

4.1.4 Client Mode

The Client Credentials Grant allows clients to authenticate to the service provider in their own name, not the user’s. Strictly speaking, the client-side pattern is not the problem that the OAuth framework addresses. In this model, users register directly with the client, and the client requests services from the “service provider” in its own name, with no authorization issues.

sequenceDiagram Client->>Authorization Server: Grant_type =client_credentials&scope={permission scope} Authorization Server-->>Client: 2. Expires_in access_token refresh_token

4.2 Updating the token

If the “access token” on the client has expired when the user accesses it, the user needs to apply for a new access token using “Update token”.

sequenceDiagram
Client->>Authorization Server: 1. grant_type=refresh_token&refresh_token={refresh_token}
Authorization Server-->>Client: 2. expires_in access_token refresh_token

4.3 wechat mini program login example

Small programs can easily obtain the user identification provided by wechat through the login ability provided by wechat official, and quickly establish the user system within small programs.

The authorization code pattern in OAuth2.0 is used. Call wx.login() to get the temporary login credential code and pass it back to the developer server. Code2Session interface is called to obtain the unique identifier of the user OpenID, the unique identifier of the user under the account of wechat Open Platform UnionID (if the current small program has been bound to the account of wechat open platform) and session key session_key. After that, the developer server can generate a custom login state based on the user id, which is used to identify the user identity during the interaction between the front and back ends in the subsequent business logic.

Fifth, JWT

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact, self-contained way to securely transfer information between parties as JSON objects. This information can be authenticated and trusted because it is digitally signed.

The most common scenario for JWT is that once the user is logged in, each subsequent request will contain the JWT, allowing the user to access the routes, services, and resources allowed by the token. Single sign-on is a feature of JWT that is widely used today because it has low overhead and can be easily used across domains.

JWT consists of three parts, separated by dots. The connection. The three parts are Header, Payload, and Signature. Thus, a typical JWT would look like this: “XXX.yyy.zzz”

The Header, the first part of the JWT, typically consists of two parts: the type (” JWT “) and the algorithm name (such as HMAC SHA256 or RSA, etc.).

{
  "alg": "HS256",
  "typ": "JWT"
}
Copy the code

Payload, the second part of the JWT, is where our data is stored. Be careful not to store sensitive information in it. It contains declarations, which are declarations about entities (usually users) and other data. There are three types of declarations: registered, public and private.

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
Copy the code

To get the Signature, you must have an encoded header, an encoded payload, a secret key, and the Signature algorithm specified in the header.

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
Copy the code

Java implementation

<dependency> <groupId> IO. Jsonwebtoken </groupId> <artifactId> JJWT </artifactId> <version>0.9.1</version> </dependency>Copy the code
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;

public class Test {
	private static final Logger logger = LoggerFactory.getLogger(Test.class);
	private static String secret = "zhongxy@123456";
	private static ObjectMapper objectMapper = new ObjectMapper();

	public static void main(String[] args) throws Exception {
		UserInfo userInfo = new UserInfo(); // A custom login object
		userInfo.setId(6);
		userInfo.setName("Test");
		logger.info("UserInfo:" + objectMapper.writeValueAsString(userInfo));

		String token = generateToken(userInfo, 60 * 1000);
		logger.info("token:" + token);

		Object result = check(token);
		logger.info("check:" + objectMapper.writeValueAsString(result));
	}

	/ / token is generated
	public static String generateToken(UserInfo userInfo, long ttlSecs) {
		//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(secret);
		Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

		//Let's set the JWT Claims
		JwtBuilder builder = null;
		try {
			builder = Jwts.builder()
                    .setIssuedAt(now)
                    .setIssuer(objectMapper.writeValueAsString(userInfo))
                    .signWith(signatureAlgorithm, signingKey);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
			return null;
		}

		//if it has been specified, let's add the expiration
		if (ttlSecs >= 0) {
			long expMillis = nowMillis + ttlSecs * 1000;
			Date exp = new Date(expMillis);
			builder.setExpiration(exp);
		}

		//Builds the JWT and serializes it to a compact, URL-safe string
		return builder.compact();
	}

	// Reverse resolve UserInfo from token
	public static UserInfo check(String token) {
		try {
			//This line will throw an exception if it is not a signed JWS (as expected)
			Claims claims = Jwts.parser()
					.setSigningKey(DatatypeConverter.parseBase64Binary(secret))
					.parseClaimsJws(token).getBody();
			String userInfoStr = claims.getIssuer();
			return objectMapper.readValue(userInfoStr, UserInfo.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null; }}Copy the code

Vi. Reference materials

  • The difference between authentication and authorization
  • CAS protocol
  • JWT
  • Ruan Yifeng understands OAuth 2.0
  • Three implementations of single sign-on
  • Wechat mini program login
  • How to Create and verify JWTs in Java