Author: Wang Hailong
Source: Wechat official account EAWorld
https://mp.weixin.qq.com/s/x0CZpovseOuofTA_lw0HvA
From single application architecture to distributed application architecture and microservice architecture, secure access of applications is constantly tested. In order to adapt to the changes of architecture and requirements, identity authentication and authentication schemes are constantly changing. How to ensure efficient and secure identity authentication in the face of calls between tens or even hundreds of microservices? How to provide a fine-grained authentication scheme for external service access? This paper will explain the security authentication and authentication scheme under the micro-service architecture.
1. Individual apps VS microservices
With the rise of microservice architecture, identity authentication and authentication in traditional single application scenarios are facing more and more challenges. In a single application system, applications are integrated. Permission verification is generally performed for all requests. Requests are generally verified by a permission interceptor, and user information is cached in the session during login and retrieved from the cache for subsequent access.
In the microservice architecture, an application is divided into several micro-applications. Each micro-application needs to authenticate access, and each micro-application needs to identify the current access users and their permissions. In particular, when the source of access is not only the browser, but also calls to other services, authentication in a single application architecture is not particularly appropriate. In the service architecture, multiple authentication scenarios, such as external application access, user-service authentication, and service-service authentication, need to be considered.
David Borsos presented four scenarios at the Microservices Conference in London:
1. Single Sign-on (SSO)
This approach means that every user-facing service must interact with an authentication service, which creates a lot of very trivial network traffic and repetitive work, especially when dozens of micro-applications are involved.
2. Distributed Session scheme
The principle of distributed session scheme is to store information about user authentication in shared storage, and the user session is usually used as the key to implement a simple distributed hash mapping. When users access microservices, user data can be retrieved from shared storage. This works well in some scenarios where the user login status is opaque. It is also a highly available and scalable solution. The disadvantage of this solution is that shared storage requires some protection and therefore needs to be accessed through secure links, which is often quite complex to implement.
3. Client Token scheme
The token is generated on the client side, signed by the authentication service, and must contain enough information to establish user identity across all microservices. Tokens are attached to each request to provide user authentication for microservices. This solution is relatively secure, but authentication logoff is a big problem and can be mitigated using short-term tokens and frequent checking of authentication services. For encoding client-side Tokens, Borsos prefers JSON Web Tokens (JWT), which is simple enough and has good library support.
4. Combine the client Token with the API gateway
This scenario means that all requests go through the gateway, effectively hiding the microservices. On request, the gateway converts the original user token to an internal session ID token. In this case, logout is not an issue because the gateway can revoke the user’s token upon logout.
Two, micro services common security authentication scheme
HTTP Basic Authentication
HTTP Basic Authentication (HTTP Basic Authentication) is an Authentication mechanism proposed by HTTP 1.0. The basic HTTP authentication process is as follows:
- The client sends an HTTP Request to the server.
- Since there is no Authorization header in the Request, the server will return a 401 unsazied to the client and add information in the header “www-authenticate” in Response.
- The client encrypts the user name and password with BASE64 and sends it in the Authorization Header to the server for successful authentication.
- The server extracts the user name and password in the Authorization Header for authentication. If the authentication succeeds, the server sends resources to the client based on the request.
Session-based authentication
- Session-based authentication is probably the most commonly used authentication mechanism. After successful login authentication, user data is stored in a Session. In a single application architecture, the default Session is stored on the application server, and the Session ID is returned to the client and stored in the Cookie of the browser.
- However, in the distributed architecture, sessions stored in a specific application server cannot be used. You can simply use Session replication or Session gluing to solve the problem.
- Session replication depends on the application server and requires the application server to have the Session replication capability. However, most application servers such as Tomcat, JBoss, and WebSphere already provide this capability.
- In addition, a major defect of Session replication is that when there are a large number of nodes, a large amount of Session data replication will occupy a lot of network resources. Session stickiness is a load balancer that distributes requests from unified users to fixed server nodes, thus ensuring that Session data is always correct for a certain user. However, this scheme depends on the load balancer, and can only meet the cluster scenario of horizontal expansion, not the distributed scenario after application segmentation.
- Under the microservice architecture, the granularity of each microservice split will be very fine, and not only users will interact with microservices, but also calls between microservices. Therefore, sessions must be separated from the application server and stored externally for centralized management. It can be a database or distributed cache, such as Memchached and Redis. This is the second solution suggested by David Borsos, the distributed Session solution.
Token-based authentication
With the rise of Restful apis and microservices, token-based authentication is now becoming more common. Tokens are different from Session ids in that they are not just keys. The Token usually contains user information. You can verify the identity by verifying the Token. Public services such as Twitter, wechat, QQ, GitHub and other apis are authenticated in this way, and some development frameworks such as OpenStack and Kubernetes internal API calls are authenticated based on Token. A typical token-based authentication process is as follows:
- The user enters the login information (or invokes the Token interface, passing in the user information) and sends it to the authentication service for authentication (the authentication service can be together with or separate from the server, depending on the micro-service split).
- The authentication service verifies whether the login information is correct, returns the interface (generally, the interface contains basic user information, permission scope, validity period and other information), and the client storage interface, which can be stored in the Session or database.
- The user places the Token in the HTTP request header and invokes the relevant API.
- The invoked microservice verifies Token permissions.
- The server returns related resources and data.
The benefits of token-based authentication are as follows:
- Stateless server: The Token mechanism does not need to store session information on the server, because the Token itself contains information about all users.
- High performance, because the Token authentication does not need to access the database or remote services for permission verification, which naturally improves performance. Supports mobile devices.
- Cross-program calls are supported. Cookies do not allow broken domain access, while tokens do not.
Iii. Introduction to JWT
Introduction to the
JSON Web Token (JWT) is an open jSON-based standard (RFC 7519) implemented for the transfer of declarations between network application environments. Abstract note from JWT RFC 7519 standardization: JSON Web Tokens are a compact, URL-safe way to represent declarations to be transmitted between two parties. JWT is generally used to pass authenticated user identity information between the identity provider and the service provider to obtain resources from the resource server, and to add some additional declarative information necessary for other business logic. The Token can also be used directly for authentication or can be encrypted.
JWT certification process
- The client invokes the login interface (or the Token interface) and passes in the user name and password.
- The server requests the authentication authority to verify that the user name and password are correct.
- The server creates the JWT and returns it to the client.
- The client takes the JWT, stores it (in the cache, in the database, or in the browser, in cookies), and adds the JWT to the HTTP request header in subsequent requests.
- The server verifies the JWT and returns related resources and data after the verification passes.
JWT structure
The JWT consists of three pieces of information. The first piece is a Header, the second piece is a Payload, and the third piece is a Signature. Each piece of content is a JSON object. Each piece of JSON object is BASE64 encoded, and the encoded content is used. The links together make up the JWT string. As follows:
header.payload.signatureCopy the code
1. Header
The header describes the most basic information about the JWT, such as its type and the algorithm used to sign it. This can also be represented as a JSON object.
{
"type" : "JWT",
"ALG" : "HS256"
}Copy the code
Indicates in the header that the signature algorithm is HS256 algorithm.
It’s a payload.
The payload is where the useful information is stored. Valid information consists of three parts:
- A declaration of registration in a standard
- Public statement
- Private declaration
Declarations registered in the standard (recommended but not mandatory) :
- Iss: JWT issuer
- Sub: The user JWT is targeting
- Aud: The side receiving the JWT
- Exp: indicates the expiration time of the JWT. The expiration time must be greater than the issue time
- NBF: Define before what time the JWT is unavailable
- Iat: issue time of JWT
- Jti: Unique IDENTIFIER of the JWT. It is used as a one-time token to avoid replay attacks.
A public statement:
- Public declarations can add any information, usually about the user or other information necessary for the business. However, it is not recommended to add sensitive information because this part can be decrypted on the client side.
Private declaration:
- Private declarations are defined by both providers and consumers. Sensitive information is generally not recommended because Base64 is symmetrically decrypted, meaning that part of the information can be classified as plaintext information.
3. Signature
Creating a signature requires Base64 encoded headers and payload and a secret key. Use the header and payload after base64 encryption. A string of concatenated strings, salted with secret combined with the encryption declared in the header, which then forms the third part of the JWT.
Such as:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)Copy the code
Advantages of JWT:
- Cross-language, JSON format ensures cross-language support
- Token-based, stateless
- It occupies small bytes and is easy to transmit
About Token logout:
Token deregistration: The Token is not stored on the server but stored on the client. When the user logs out, the Token is still valid. So how to cancel the Token when the user logs out is a point to pay attention to. Generally, there are the following ways:
- The Token is stored in a Cookie, which can be automatically cleared when the client logs out
- When a Token is deregistered, the Token is stored in the distributed cache, and the time zone is verified each time to check whether the Token is deregistered. However, this also loses the advantage of quick verification of the Token.
- Use short-term tokens, such as Token validity period of 20 minutes, to reduce the risk of Token availability after deregistration to some extent.
The 2.0 introduction
OAuth’s official website: An open protocol to allow secure API authorization in a simple and standard method from desktop and Web Applications.
OAuth is an open protocol that provides a simple, standard way for desktop applications or BS-BASED Web applications to access API services that require user authorization. OAUTH authentication and authorization has the following characteristics:
- Simple: Easy to understand and use for both OAuth service providers and application developers;
- Security: does not involve the user key and other information, more secure and flexible;
- Open: Any service provider can implement OAuth and any software developer can use OAuth;
OAuth 2.0 is the next version of the OAuth protocol, but it is not backward compatible with OAuth 1.0, that is, OAuth 1.0 is completely abolished.
OAuth 2.0 focuses on simplicity for client developers. Either by organizing approved interactions between the resource owner and the HTTP service provider on behalf of the user, or by allowing third-party applications to gain access on behalf of the user. It also provides a dedicated certification process for Web applications, desktop applications and mobile, and living room devices.
In October 2012, OAuth 2.0 was officially released as RFC 6749.
Authorization process
The OAuth 2.0 process is as follows:
- (A) After the user opens the client, the client requires the user to grant authorization.
- (B) The User agrees to authorize the Client.
- (C) The client applies for a token from the authentication server using the authorization obtained in the previous step.
- (D) After authenticating the client, the authentication server confirms that it is correct and agrees to issue the token.
- (E) The client uses the token to apply to the resource server for obtaining resources.
- (F) The resource server confirms the token and agrees to open the resource to the client.
The four roles
From the authorization flow chart, we can see that OAuth 2.0 has four roles: client, resource owner, resource server, and authorization server.
- Client: A client is an application that makes a request to a resource server to access a protected resource on behalf of the resource owner.
- Resource owner: A resource owner is a person who has the ability to authorize a resource.
- Resource server: The server where the resource resides.
- Authorization server: Provides different tokens for client applications, either on the same server as the resource server or independently.
Client authorization mode
Clients must obtain Authorization grants from users to obtain access tokens. OAuth 2.0 defines four authorization modes: AuthorizationCode, Implicit, Resource Owner Password credentials, and Client credentials.
1. Authorization Code
The Authorization Code mode is the most complete authorization mode with the most rigorous procedures. It features interaction with the authentication server of the “service provider” through the backend server of the client. The process is as follows:
- The user accesses the client, which directs the former to the authentication server.
- The user selects whether to authorize the client.
- Assuming that the user has granted authorization, the authentication server directs the user to the redirection URI (URI) specified by the client, along with an authorization code.
- The client receives the authorization code, along with the earlier “redirect URI,” and requests a token from the authentication server. This step is done on the server in the background of the client and is not visible to the user.
- After verifying the authorization code and redirection URI, the authentication server sends the Access token and refresh token to the client.
Implicit patterns are implicit.
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. The process is as follows:
- The client directs the user to the authentication server.
- The user decides whether to grant authorization to the client.
- Assuming authorization from the user, the authentication server directs the user to the “redirect URI” specified by the client and includes the access token in the Hash part of the URI.
- The browser makes a request to the resource server that does not include the Hash value received in the previous step.
- The resource server returns a web page containing code to retrieve the token in the Hash value.
- The browser executes the script obtained in the previous step and extracts the token.
- The browser issues the license to the client.
3. Resource Owner Password Credentials
In password mode, the user provides the user name and password to the client. The client uses this information to request authorization from the “service provider.” In this mode, the user must give his password to the client, but the client cannot store the password. This is usually used when the user has a high degree of trust in the client, such as when the client is part of the operating system or is produced by a well-known company. Authentication servers can only consider using this mode if other authorization modes cannot be implemented. The process is as follows:
- The user provides the user name and password to the client.
- The client sends the user name and password to the authentication server, which requests the token.
- After the authentication server confirms that it is correct, it provides the access token to the client.
4. Client Credentials
- 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. The process is as follows:
- The client authenticates to the authentication server and asks for an access token.
- After the authentication server confirms that it is correct, it provides the access token to the client.
Fifth, thinking summary
- As suggested by David Borsos, we prefer to combine Oauth and JWT in microservice architecture. Oauth is generally used in third-party access scenarios to manage external permissions, so it is more suitable to combine with API gateway to authenticate external access (of course, JWT is also acceptable as the underlying Token standard).
- JWT is lighter, allows access authentication between microservices to suffice, and avoids dealing with authentication services in the flow. Of course, from the perspective of capability implementation, similar to distributed Session can also fully meet the requirements in many scenarios. How to select an authentication scheme should be based on the actual requirements.
Follow the public account “Architecture Digest”, every day a great article in the field of architecture, covering the application architecture of first-tier Internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture and other hot fields.