DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Jakarta Security and REST in the Cloud: Part 2 Getting to Know the Basics
  • How to Develop Microservices With Spring Cloud and Netflix Discovery
  • Reactive Elasticsearch With Quarkus
  • Ultra-Fast Microservices: When MicroStream Meets Helidon

Trending

  • Operational Principles, Architecture, Benefits, and Limitations of Artificial Intelligence Large Language Models
  • Building a Real-Time Change Data Capture Pipeline With Debezium, Kafka, and PostgreSQL
  • How to Convert XLS to XLSX in Java
  • Customer 360: Fraud Detection in Fintech With PySpark and ML
  1. DZone
  2. Data Engineering
  3. Databases
  4. Jakarta Security and REST in the Cloud Part 1: Hello World

Jakarta Security and REST in the Cloud Part 1: Hello World

There is not enough discussion about Security, but there should be.

By 
Otavio Santana user avatar
Otavio Santana
DZone Core CORE ·
Jun. 11, 20 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
5.7K Views

Join the DZone community and get the full member experience.

Join For Free

Despite being a crucial aspect of any application, security is a topic that few discuss in the software development industry. As a consequence, many decisions are made without taking this issue into account.

This is a series of articles that will talk about security in the Jakarta EE world with Jakarta Security with microservices in the cloud. In this first part, we will create the “Hello world” of security; we will discuss a little about its importance, the most common mistakes, and create our first contact with the Jakarta Security API.

Much has been said about information security, but after all, what does it mean? Information security is related to the protection of data for users and the company itself, based on the pillars of ISO / IEC 17799: 2005:

  • Confidentiality: Property that limits access to information only to legitimate entities, that is, those authorized by the information owner.

  • Integrity: Property that guarantees that the manipulated information maintains all the original characteristics established by the information owner, including change control and a guarantee of its life cycle (current, intermediate and permanent).

  • Availability: Property that guarantees that the information is always available for legitimate use, that is, by those users authorized by the information owner.

  • Authenticity: Property that guarantees that the information comes from the advertised source and that it has not been subject to changes during a process.

Security problems result in enormous losses for companies, whether in the short, medium, or long term. After all, even after the correction is carried out by the company, it takes time to revert to the level of trust and credibility that company had before the event, giving a great advantage to the competition.

First Java Security Tips

An excellent way to start talking about security in Java starts with some simple tips to avoid breaches in our system. So, here we list the biggest security mistakes:

  1. Encapsulation: It is impossible to start with security problems and not mention the biggest challenge in Java applications: encapsulation problems. Indeed, in addition to being a code smell problem leaving all classes and attributes public, this attitude generates several data integrity problems. After all, the big point about OOP, according to the principles of keeping “clean” code, is the fact of hiding the data to expose the behavior. It is vital to always think about having a protected API.

  2. Concatenated queries: A widespread problem is allowing queries from concatenated strings. Doing so may result in SQL Injections.

  3. Beware of the Log: The log is an important point, both for checking behavior and for checking bugs. It is imperative to pay attention to the fields that will be exposed in the “toString”, for example.

  4. Caution when exposing sensitive data: Very common in microservices. It is important to know what information will be exposed and to whom. There are a few ways to avoid this by thinking only about microservices. For example, using the notation that ignores the field to be serialized, or explaining the data that will be exposed by creating a DTO layer.

  5. Avoid Java serialization: It is vital to pay attention to the use of this interface. There are several security problems in it, so use the Serializable interface only if necessary. Remember that, in the vast majority of cases, its use is not recommended.

  6. Watch out for encryption or hashing algorithms: Obviously, the use of encryption is significant, so be careful with implementation.

  7. Attention to your dependencies: Several studies estimate that about 90% of the code that is put into production is related to third party projects. Thus, it is imperative to have due attention when updating software, including the JVM itself. Keep in mind that in addition to new features and performance improvements, updates help to fix a variety of security issues if we do it often enough.

  8. Database password: This is one of the biggest security problems. Avoid putting the password inside the code. The Twelve Factor App talks a lot about the advantages of configuration. In addition, NoSQL does not mean "NoSecurity", so it is important to enter a password or restrict access to this type of database. There is a study that says that about 75% of Redis banks that are exposed to the public do not use a password.

  9. Access to servers and databases: This problem is much more related to operations. However, it is crucial to check access to servers and databases. That is, server access the databases they need and that only public access servers and the necessary ports must be exposed.

  10. Using security tools is not a bad thing. There are now tools that manage security, and experts are focused on that. Much worse than paying for an expensive and mature solution, it is reinventing the wheel with a solution that causes several security problems, not to mention that it results in a waste of time and great work, making the focus leave our business.

An excellent tip to avoid a large number of these security errors is to look at the top 10 best Java security practices written by Snyk.

Hello World

After explaining the security concepts, let's create a Hello World application using Payara and the security API provided by Jakarta EE. We will create several resources, and each of them will return a simple text. However, each available service will have its own permission rule, given that we have three access rules (manager, user, and admin) and we will have the following services:

  • One that everyone can access without any problem.

  • One that only the admin accesses.

  • One that only the manager and admin can access.

  • One that the user accesses.

  • One that no one accesses, but what is the purpose of this example? It would be a feature that is not available to any user yet.

If we already work with JAX-RS, then we are used to creating a class that will inherit Application and will have the ApplicationPath notation. This class will safely have some more information. In that case, we will define the rules that will be used in the application. In our case, we will also use one of the authentication mechanisms that the API already provides.

By default, the Jakarta EE security API provides the following authentication mechanisms:

  • BasicAuthenticationMechanismDefinition

  • FormAuthenticationMechanismDefinition

  • CustomFormAuthenrticationMechanismDefinition

In this case, we will use the Basic mechanism, which we will not explain in this article because we will have a text entirely dedicated to that mechanism.

Java
xxxxxxxxxx
1
13
 
1
import javax.annotation.security.DeclareRoles;
2
import javax.enterprise.context.ApplicationScoped;
3
import javax.security.enterprise.authentication.mechanism.http.BasicAuthenticationMechanismDefinition;
4
import javax.ws.rs.ApplicationPath;
5
import javax.ws.rs.core.Application;
6

          
7
@ApplicationPath("")
8
@BasicAuthenticationMechanismDefinition(realmName = "userRealm")
9
@ApplicationScoped
10
@DeclareRoles({"ADMIN", "MANAGER", "USER"})  // You need to indicate all roles that are used by the app
11
public class ApplicationConfig extends Application {
12
}


As soon as the user sends the information via Basic, we will need to validate the credentials. That is, the user first authenticates themselves so that they can be verified. In Jakarta EE Security, this validation process is performed thanks to the IdentityStore, which can have several implementations, such as database, files, or LDAP. In our example, this will be really simple and everything will be managed by the memory and the username.

Java
xxxxxxxxxx
1
41
 
1
import javax.enterprise.context.ApplicationScoped;
2
import javax.security.enterprise.credential.Credential;
3
import javax.security.enterprise.credential.UsernamePasswordCredential;
4
import javax.security.enterprise.identitystore.CredentialValidationResult;
5
import javax.security.enterprise.identitystore.IdentityStore;
6
import java.util.Collections;
7

          
8
import static javax.security.enterprise.identitystore.CredentialValidationResult.INVALID_RESULT;
9

          
10
@ApplicationScoped
11
public class InMemoryIdentityStore implements IdentityStore {
12

          
13
    @Override
14
    public int priority() {
15
        return 10;
16
    }
17

          
18
    @Override
19
    public CredentialValidationResult validate(Credential credential) {
20

          
21
        if (credential instanceof UsernamePasswordCredential) {
22
            UsernamePasswordCredential user = UsernamePasswordCredential
23
                    .class.cast(credential);
24

          
25
            switch (user.getCaller()) {
26
                case "admin":
27
                    return new CredentialValidationResult("admin", Collections.singleton("ADMIN"));
28
                case "manager":
29
                    return new CredentialValidationResult("admin", Collections.singleton("MANAGER"));
30
                case "user":
31
                    return new CredentialValidationResult("admin", Collections.singleton("USER"));
32
                default:
33
                    return INVALID_RESULT;
34
            }
35

          
36
        }
37
        return INVALID_RESULT;
38
    }
39

          
40
}


After this super validation mechanism, the last step is to create the services and identify them according to the permission rule.

Java
xxxxxxxxxx
1
52
 
1
import javax.annotation.security.DenyAll;
2
import javax.annotation.security.PermitAll;
3
import javax.annotation.security.RolesAllowed;
4
import javax.enterprise.context.RequestScoped;
5
import javax.ws.rs.GET;
6
import javax.ws.rs.Path;
7
import javax.ws.rs.Produces;
8

          
9
@Path("")
10
@RequestScoped
11
public class HelloWorldResource {
12

          
13
    @GET
14
    @PermitAll
15
    @Produces("text/plain")
16
    public String doGet() {
17
        return "hello from everyone";
18
    }
19

          
20
    @Path("admin")
21
    @GET
22
    @RolesAllowed("ADMIN")
23
    @Produces("text/plain")
24
    public String admin() {
25
        return "hello from admin";
26
    }
27

          
28
    @Path("manager")
29
    @GET
30
    @RolesAllowed({"MANAGER", "ADMIN"})
31
    @Produces("text/plain")
32
    public String manager() {
33
        return "hello from manager";
34
    }
35

          
36
    @Path("user")
37
    @GET
38
    @RolesAllowed({"MANAGER", "ADMIN", "USER"})
39
    @Produces("text/plain")
40
    public String user() {
41
        return "hello from user";
42
    }
43

          
44
    @Path("nobody")
45
    @GET
46
    @DenyAll
47
    @Produces("text/plain")
48
    public String nobody() {
49
        return "hello from nobody";
50
    }
51
}


The application is ready for us to use! An interesting thing about this example is that we can test the returns and the respective codes, as in the 401 and 403 situations.

Moving to the Cloud

I have had the pleasure of talking several times about the advantages of using cloud computing without commenting on its risk, according to the type of service that was chosen. One of the significant benefits of PaaS is the abstraction of the infrastructure layer, considerably reducing the risk of migration to the cloud, including security. Having a service team that will be responsible for controlling access to servers and containers within the cluster, in addition to the database update process and backup automation, are critical, highly abstract points that a PaaS can offer.

To facilitate the migration of local code to a cloud environment, we will use a PaaS, in this case, Platform.sh. In a nutshell, it is the second generation of PaaS from which it will manage all resources for us following the concept of infrastructure as code. Push our Git repository, and the PaaS will be responsible for creating the containers, configuring access permissions within the cluster, and finalizing the deployment in production.

To do the deployment, we need three files: One to define the application information, another for the services that the application needs, and the last to define the routes. So that we will have the following:

YAML
xxxxxxxxxx
1
 
1
"https://{default}/":
2
  type: upstream
3
  upstream: "app:http"
4
5
"https://www.{default}/":
6
  type: redirect
7
  to: "https://{default}/"


To configure the application:

YAML
xxxxxxxxxx
1
 
1
name: app
2
type: "java:11"
3
disk: 1024
4
hooks:
5
    build:  mvn clean package payara-micro:bundle
6
web:
7
    commands:
8
        start: java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError target/microprofile-microbundle.jar --port $PORT


As we use everything in memory, it is not necessary to use the service file.

In this article, we talk a little about the security aspect, the importance of thinking about it. An important code-level thing was that we were able to make this practical example with just three classes. This clearly demonstrates that there has been a considerable improvement in the security API within the Java specifications. In the second part, we will talk a little about BASIC, its advantages and disadvantages. To see the final application of this series, take a look at this link.

Information security Cloud computing REST Web Protocols Database application Java (programming language) microservice

Opinions expressed by DZone contributors are their own.

Related

  • Jakarta Security and REST in the Cloud: Part 2 Getting to Know the Basics
  • How to Develop Microservices With Spring Cloud and Netflix Discovery
  • Reactive Elasticsearch With Quarkus
  • Ultra-Fast Microservices: When MicroStream Meets Helidon

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!