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

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Authentication With Remote LDAP Server in Spring WebFlux
  • Authentication With Remote LDAP Server in Spring Web MVC
  • How to Implement Two-Factor Authentication in A Spring Boot OAuth Server? Part 2: Under the Hood
  • Implementing Authentication and Authorization With Vaadin

Trending

  • Scaling DevOps With NGINX Caching: Reducing Latency and Backend Load
  • Medallion Architecture: Efficient Batch and Stream Processing Data Pipelines With Azure Databricks and Delta Lake
  • Optimizing Integration Workflows With Spark Structured Streaming and Cloud Services
  • The Role of Functional Programming in Modern Software Development
  1. DZone
  2. Coding
  3. Frameworks
  4. Spring Security With LDAP Authentication

Spring Security With LDAP Authentication

In this article, an author shares their experience with Spring Security on a demo purpose application of which the source code is available on Github.

By 
Dilek Karadaş Mataracı user avatar
Dilek Karadaş Mataracı
·
Sep. 13, 21 · Tutorial
Likes (9)
Comment
Save
Tweet
Share
27.7K Views

Join the DZone community and get the full member experience.

Join For Free

In real-world applications on production systems; security is a top concern. This security concern is separated into two: Authentication and Authorization. Authentication mainly focuses on who can access to the application and authorization focuses on who can access which resources based on their authorities. 


Spring Security logo.


In this article I will share my experience with Spring Security on a demo purpose application of which source code is available on Github. In this project, I used LDAP Authentication method for authentication. For the token generation mechanism, I used a private/public RSA key method. Private key is used for token generation and public key is used for token validation.  

The aim of the project is to return a jwt token to the login user and the user will use this token to access resources in subsequent requests. The demo application offers two rest endpoints: one is for the authentication mechanism to take place (/auth-server) and the other is a representative rest resource (/resource). Anyone can access the "/auth-server" endpoint, but the access is restricted to the "/resource" endpoint. When the user logs into the system; there will be a rest call to the "/auth-server" endpoint for LDAP authentication. For successful authentication, there will be a jwt token in the response. The second rest call will be to the actual resource endpoint "/resource" with the token in the header as an Authentication object. We will see how this is done in the codebase.

It is very simple to enable Spring Security in your projects. You can do that by only adding a few dependencies. Let’s start to examine our demo application to see how things are done.

First; the two dependencies below will be added to the pom.xml to enable Spring Security. You can do this also when generating the project structure in spring initializer by adding Spring Security Component.

XML
 
	<dependency>
        	<groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
	</dependency>

	<dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
	</dependency>


Apart from these, we need to add additional dependencies for LDAP. Spring gives us the opportunity to use an embedded LDAP server.


XML
 
	<dependency>
		<groupId>com.unboundid</groupId>
		<artifactId>unboundid-ldapsdk</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.ldap</groupId>
		<artifactId>spring-ldap-core</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.security</groupId>
		<artifactId>spring-security-ldap</artifactId>
	</dependency>


Security configuration is done based on a configuration file:

Java
 
@Configuration
@EnableWebSecurity
public class DemoSecurityConfiguration extends WebSecurityConfigurerAdapter
{
    private Environment env;
    public DemoSecurityConfiguration(Environment env){
        this.env = env;
    }
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception
    {
        auth.authenticationProvider(new LdapAuthenticationProvider(env)).eraseCredentials(false); 
    }
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception 
    {
        httpSecurity
                .authorizeRequests()
                .antMatchers("/auth-server").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable()
                .httpBasic();
    }
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
   @Bean
    public JwtTokenProvider provider(){
        return new JwtTokenProvider();
    }
}


The @EnableWebSecurity annotation is used for enabling spring web security. Configuration class must extend from Spring’s WebSecurityConfigurerAdapter class. First, the configure method is needed for defining the authentication method. The second configure method is to define security properties. For authentication, I created a custom LdapAuthenticationProvider class. Inside the second configure method, we are authorizing any request to the endpoint “/auth-server,” but the other endpoints should be authenticated first. We disable CSRF and we use an HTTP basic authentication.

For an embedded LDAP server, in the application.properties file we should define some properties:

Properties files
 
spring.ldap.embedded.port=8389
spring.ldap.embedded.ldif=classpath:ldap.ldif 
spring.ldap.embedded.base-dn=dc=springframework,dc=org


We will read the LDAP structure from a LDIF file(ldap.ldif); LDAP server’s port will be 8389; the root directory will be dc=springframework,dc=org.

Below is the custom LDAP authentication provider class:

Java
 
@Component
public class LdapAuthenticationProvider implements AuthenticationProvider
{
    private Environment environment;
    public LdapAuthenticationProvider(Environment environment) {
        this.environment = environment;
    }
    private LdapContextSource contextSource;
    private LdapTemplate ldapTemplate;
    private void initContext()
    {  
        contextSource = new LdapContextSource();
        contextSource.setUrl(environment.getProperty("ldap.server.url"));
        contextSource.setAnonymousReadOnly(true);
        contextSource.setUserDn("uid={0},ou=people");
        contextSource.afterPropertiesSet();

        ldapTemplate = new LdapTemplate(contextSource);
    }
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException
    {
        initContext();
        Filter filter = new EqualsFilter("uid", authentication.getName());
        Boolean authenticate = ldapTemplate.authenticate(LdapUtils.emptyLdapName(), filter.encode(), authentication.getCredentials().toString());
        if (authenticate)
        {
            UserDetails userDetails = new User(authentication.getName(), authentication.getCredentials().toString()
                    , new ArrayList<>());
            Authentication auth = new UsernamePasswordAuthenticationToken(userDetails,
                    authentication.getCredentials().toString(), new ArrayList<>());
            return auth;
        }
        else
        {
            return null;
        }
    }

    @Override
    public boolean supports(Class<?> authentication)
    {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}


The first LdapContext is prepared after an EqualsFilter operation is done based on the uid(username). If a match happens with the correct password, then an Authentication object is prepared and returned. Otherwise, it returns null.

After successful authentication, the JWTTokenProvider class prepares a token with below method: generateToken:

Java
 
public class JwtTokenProvider
{
    public static String generateToken(String userName) throws Exception
    {
        Instant now = Instant.now();
        String jwtToken = Jwts.builder()
                .claim("name", userName)
                .setSubject("jwt_token")
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(Date.from(now))
                .setExpiration(Date.from(now.plus(5l, ChronoUnit.MINUTES)))
                .signWith(SignatureAlgorithm.RS512, getPrivateKey())
                .compact();
        return jwtToken;
    }
    private static Key getPrivateKey() throws Exception
    {
        ClassLoader classLoader = JwtTokenProvider.class.getClassLoader();
        File file = new File(classLoader.getResource("private.key").getFile());
        byte[] rsaPrivateKeyArr = FileUtils.readFileToByteArray(file);
        String rsaPrivateKey = new String(rsaPrivateKeyArr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(rsaPrivateKey));
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(keySpec);
    }	
}


I used private/public RSA key method to generate the token. I generated a private key with the OpenSSL genrsa command and put this private key to a resource file as "private.key" in/resources folder. The jwt token is prepared based on this private key in generateToken method. Also, an expiration time can be set to the token with the setExpiration method.

In postman, we can call the rest endpoints as follows:Rest Endpoints screenshot 1.

Rest Endpoints screenshot 2.

Thanks for reading!

You can find the source code at Github.

Spring Security authentication Spring Framework

Opinions expressed by DZone contributors are their own.

Related

  • Authentication With Remote LDAP Server in Spring WebFlux
  • Authentication With Remote LDAP Server in Spring Web MVC
  • How to Implement Two-Factor Authentication in A Spring Boot OAuth Server? Part 2: Under the Hood
  • Implementing Authentication and Authorization With Vaadin

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!