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

  • Installing and Debugging an Apereo Cas Application
  • Building Resilient Identity Systems: Lessons from Securing Billions of Authentication Requests
  • Secure by Design: Modernizing Authentication With Centralized Access and Adaptive Signals
  • Understanding IEEE 802.11(Wi-Fi) Encryption and Authentication: Write Your Own Custom Packet Sniffer

Trending

  • How To Introduce a New API Quickly Using Quarkus and ChatGPT
  • Strategies for Securing E-Commerce Applications
  • Simpler Data Transfer Objects With Java Records
  • Optimizing Serverless Computing with AWS Lambda Layers and CloudFormation
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Apereo CAS: Step by Step Guide To Implement a Custom Authentication Handler

Apereo CAS: Step by Step Guide To Implement a Custom Authentication Handler

In this article, we are going to look into the details of implementing a custom authentication handler in an Apereo CAS application.

By 
Upul Kamburawala user avatar
Upul Kamburawala
·
Oct. 10, 21 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
6.7K Views

Join the DZone community and get the full member experience.

Join For Free

As described in a previous article about getting an Apereo CAS application up and running, we used the default username and password to log in to the CAS. But in a real-world scenario, we need to implement some sort of mechanism to authenticate a user. It is more common to use an authentication handler for this purpose. In this article, we are going to look into the details of implementing a custom authentication handler in an Apereo CAS (hereafter it will be simply referred to as CAS) application.

Note: Additional implementational details are available inside the following code blocks as Java comments.

Following are steps for implementing a custom authentication handler:

  • Import the CAS overlay project into the eclipse IDE.
  • Before we start any coding, you need to make sure you have the following dependencies in your build.gradle file:
Java
 
dependencies {
	.....
    // Other CAS dependencies/modules may be listed here...
    compile"org.apereo.cas:cas-server-support-json-service-registry:${casServerVersion}"
    compile"org.apereo.cas:cas-server-core-authentication-api:${casServerVersion}"
    compile"org.apereo.cas:cas-server-core-web-api:${casServerVersion}"
    compile"org.apereo.cas:cas-server-core-util-api:${casServerVersion}"

}
  • The next step is to define the authentication handler class. The role of this class is to validate credentials and send back the result to the client. Create a package in the "src/main/java" folder and create a new class inside this package. This class should extend “AbstractUsernamePasswordAuthenticationHandler” available in the "org.apereo.cas.authentication.handler.support " package. The following code snippets should depict to you what a custom authentication handler looks like.

Java
 
Public class MyAuthHandler extends AbstractUsernamePasswordAuthenticationHandler{
	
  	/* If you want to make availble custom properties defined in 
  	 "cas.properties" file in to this class*/
    @Autowired
	private CasConfigurationProperties casProperties;
  
  	Public MyAuthHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) {
            super(name, servicesManager, principalFactory, order);
    }

  	@Override
    Protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(finalUsernamePasswordCredentialcredential,
        final String originalPassword) throws GeneralSecurityException {

    //If login failed throw an exception
    if (!isSuccesfulLogin())) {
        throw new FailedLoginException();
    }

    //If login is successful, then create and return back the resolved user //details. If there are additional parameter such as warning about the //password Can be passed inside the “ArrayList()” 
    AuthenticationHandlerExecutionResult principle = createHandlerResult(credential,
        this.getPrincipalFactory( ).createPrincipal( id, user), new ArrayList<>(0) );
        return principle;
    }
}
  • Next, we will look into how to implement the “authenticateUsernamePasswordInternal” method in detail. The following code snippets illustrate these details:
Java
 
@Override
protected AuthenticationHandlerExecutionResult  authenticateUsernamePasswordInternal(finalUsernamePasswordCredentialcredential,
	final String originalPassword) throwsGeneralSecurityException {

    //username and password can be extracted from the credential parameter
    String username = credential.getUsername();
    String password = credential.getPassword();

    //If there is any other additional parameter, if you want pass from the login 
    //page, then you can retrieve them in HTTP request object
    HttpServletRequest requestObj = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();

    String otherparam = (String)requestObj.getParameter("otherparam");
	
  	//If you want to pass any properties to authenticator class, pass "casProperties" here 
  	MyAuthenticator authenticator = new MyAuthenticator(casProperties);
    
  	/*Authenticate the user credentials using some mechanism like 
    verifying them against the data available in a database */
    User userObj=authenticator.login(username, password);

    final Map<String,List<Object>> attributes= new HashMap<String,List<Object>>();
    final Map<String, Object>user = new HashMap<>();
    final List<Object> userInfo = new ArrayList<>();

    if (userObj != null && userObj.isSuccesfulLogin())) {

    	user.put("id", userObj.id());
            user.put("firstname", userObj.getFirstname());
            user.put("lastname",userObj.getSurname());
            user.put("username", userObj.getUsername());
            user.put("email", userObj.getEmail());
            user.put("roles", StringUtils.join(userObj.listRoles(), ","));

    }else{
    	throw new FailedLoginException();

    }

    userInfo.add(user);
    attributes.put("attributes", userInfo);

   /* In the last parameter, you can pass back set of warnings related to the credentials 
   and show them user if needed as ArrayList<> object. In this example we don't send any.
   */
    AuthenticationHandlerExecutionResult principal = createHandlerResult(credential,
    this.getPrincipalFactory().createPrincipal( id, attributes), new ArrayList<>(0) );

   // return back the resolved principal
    return principal;	

}
  • Once the handler class is ready, it needed to be registered with CAS. CAS is built on the Java Spring framework. Therefore this can be done through a configuration class. All we do in this class is create a bean of the MyAuthHandler class, which we create in the previous step, and register it as a CAS Authentication plan. Create another package inside the "src/main/java" folder and create a class in it. Following is how this configuration class looks:
Java
 
@Configuration("MyAuthenticationEventExecutionPlanConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
Public class MyAuthenticationEventExecutionPlanConfiguration implements AuthenticationEventExecutionPlanConfigurer{

    @Autowired
    private CasConfigurationProperties casProperties;

  /*here in 4th parameter, we can set the order of this handler is executed by CAS,
      if there are multiple authentication stratagies are avaible */
    @Bean
    Public AuthenticationHandler myAuthHandler() {
    	final MyAuthHandler handler = new MyAuthHandler("authHandler", null,null ,1, casProperties);
	    return handler;
    }

    @Override
    Public void configureAuthenticationExecutionPlan(AuthenticationEventExecutionPlan plan) {
            plan.registerAuthenticationHandler(myAuthHandler());
    }	
	
}
  • As the final step, we need to make sure our handler is available to the CAS. For this, create the “META-INF” folder inside the "src\main\resources" folder of your project. Add a file with the name “spring.factories” inside the above-created folder. Add the following line to that file:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.myorg.config.AuthenticationEventExecutionPlanConfigurer

  • Now go to the root folder of the project in the command prompt and give the command to start the server. On the startup console, there should be a log message you can see our handle is binding to CAS runtime.

Now if you are going to log in through the login page, our authentication handler will be executed and our custom authentication will be used. In another article, we are going to see how to customize the user interface of the CAS application.

Central Authentication Service authentication

Opinions expressed by DZone contributors are their own.

Related

  • Installing and Debugging an Apereo Cas Application
  • Building Resilient Identity Systems: Lessons from Securing Billions of Authentication Requests
  • Secure by Design: Modernizing Authentication With Centralized Access and Adaptive Signals
  • Understanding IEEE 802.11(Wi-Fi) Encryption and Authentication: Write Your Own Custom Packet Sniffer

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!