Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

Implementing Authentication for servlet on publish instance

Avatar

Level 4

Hi,

I have a scenario and any suggestions in implementing that will be of great help. I have a servlet created on publish that will have POST requests coming from a lot of other third party applications. This servlet just stores the incoming posted data in JCR. I have successfully created this servlet but now the requirement is to make this servlet secured so that only applications hitting this servlet with particular username and password should be entertained.

Has anyone knowledge on what I can do to achieve this.

Thanks,

Samir

1 Accepted Solution

Avatar

Correct answer by
Level 9

Hi Samir,

Use UserManager API in your servlets which handles are the request from third party applications. Through UserManager API, you could extract individual user profiles to do validation against given parameters.

Here is the doc which could help you.

http://wemcode.wemblog.com/user-group-management

https://docs.adobe.com/docs/en/aem/6-0/develop/ref/javadoc/org/apache/jackrabbit/api/security/user/U...

Jitendra

$@^^!R wrote...

Hi,

I have a scenario and any suggestions in implementing that will be of great help. I have a servlet created on publish that will have POST requests coming from a lot of other third party applications. This servlet just stores the incoming posted data in JCR. I have successfully created this servlet but now the requirement is to make this servlet secured so that only applications hitting this servlet with particular username and password should be entertained.

Has anyone knowledge on what I can do to achieve this.

Thanks,

Samir

 

View solution in original post

11 Replies

Avatar

Correct answer by
Level 9

Hi Samir,

Use UserManager API in your servlets which handles are the request from third party applications. Through UserManager API, you could extract individual user profiles to do validation against given parameters.

Here is the doc which could help you.

http://wemcode.wemblog.com/user-group-management

https://docs.adobe.com/docs/en/aem/6-0/develop/ref/javadoc/org/apache/jackrabbit/api/security/user/U...

Jitendra

$@^^!R wrote...

Hi,

I have a scenario and any suggestions in implementing that will be of great help. I have a servlet created on publish that will have POST requests coming from a lot of other third party applications. This servlet just stores the incoming posted data in JCR. I have successfully created this servlet but now the requirement is to make this servlet secured so that only applications hitting this servlet with particular username and password should be entertained.

Has anyone knowledge on what I can do to achieve this.

Thanks,

Samir

 

Avatar

Employee Advisor

I would recommend you to bind this servlet to a page path using the resource type and then use closed user group feature in AEM to secure this path on the publish instance. You need to expose only the page path to your external applications. If they request the page with authentication then they will be granted access otherwise it redirects to the login page. 

See the following pages for more details- 

[1] https://cqdump.wordpress.com/2015/03/23/aem-coding-best-practice-servlets/

[2] https://helpx.adobe.com/experience-manager/kb/HowToSetupCUG.html

[3] https://docs.adobe.com/docs/en/aem/6-1/administer/security/cug.html

Avatar

Level 9

In my view, using CUG would be difficult to do with a given case. Third party applications are posting some data & that data has to store in JCR. What would happen if third party API which hits our servlet gets login page in response?.

Jitendra

Avatar

Level 4

Yes jeetendra completely agree with you. That wont suffice my requirement. To really tell you about the scenario its like an SAP system which has some form which has to submit that data to CQ thrrough SOAP webservice. For the same I have created a SOAP webservice and deployed in an Tomcat app server. That webservice gets the data from SAP and the posts the same to CQ5. Now I dont want any random application to submit to my servlet, so for that I thought of bringing in some authentication mechanism which makes CQ5 identify that its authorized application requesting submit on my servlet.

For now I have manually added the authorization in webservice connection which calls the servlet with encoded username password as admin:admin and in CQ5 servlet I am decoding the same using Base64 decoder and checking if its admin admin, only then I am writing the data into JCR. Now I know this is just an workaround approach and hence looking for a more recommended way to achieve the same. Also I know still anyone can sniff the authorization from packets and decode and see the username but I have been told that if CQ5 will be on SSL, noone will be able to see the username password. But still I feel thats not the correct way. Any help with this ? 

Avatar

Level 9

Samir,

if it is just about making username/password secure, you could use java.security & javax.crypto.* API for encryption & decryption. AEM does have crypto support API.

https://docs.adobe.com/docs/en/aem/6-1/ref/javadoc/

Jitendra

Avatar

Employee Advisor

Hi,

first question: why don't you deploy your webserver in AEM? You can bring a bundle which contains all the logic and libraries to do the webservice call, and then directly persist the data.

Regarding the authentication: Please use the approach described by kunal and bind your servlet to a resourcetype; then create a page using this resourcetype and protected this page via ACLs; you can configure AEM/Sling to accept basic authentication. And then everything should work. Do not implement authentication on your own!

kind regards,
Jörg

Avatar

Level 4

Jörg Hoh wrote...

Hi,

first question: why don't you deploy your webserver in AEM? You can bring a bundle which contains all the logic and libraries to do the webservice call, and then directly persist the data.

Regarding the authentication: Please use the approach described by kunal and bind your servlet to a resourcetype; then create a page using this resourcetype and protected this page via ACLs; you can configure AEM/Sling to accept basic authentication. And then everything should work. Do not implement authentication on your own!

kind regards,
Jörg

 

Hi Jorg,

I am not consuming the SOAP webservice, but hosting it, thats the reason I created/deployed that webservice on a seperate Tomcat server as .war file. Do you mean we can create the webservice in CQ5 ? or can we deploy that .war in CQ5 ?

Regarding kunal's approach, I have not clearly understood the approach. If you can clarify on my understanding I will be able to implement the same way. Does he mean I have to declare the servlet like below : 

@SlingServlet(resourceTypes = "/apps/myproject/components/mycomponent", methods = {"POST", "GET"}, metatype=true) public class MyServlet extends SlingAllMethodsServlet{

and then the same component, I will use an any Page's sling:resourceType like below :

sling:resourceType = "/apps/myproject/components/mycomponent"

And what about the script of /apps/myproject/components/mycomponent . Should I write any html, jsp there or there is no need for any script ?

Also one more thing will be if the basic authentication fails for such CUG restricted pages, then it will show the login page which is not needed in my case as it will be accessed through Java code, we can't show login page. Also in my webservice do I need to post data to the page instead of servlet like below :

String servleturltopost = "http://localhost:4503/content/site/pagewithcug.html"; String param = "data=somejsondata";     URL url = new URL(servleturltopost); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); String authStr = "testuser"+":"+"testuserforcug"; // encoding data using BASE64 byte[] bytesEncoded = Base64.encodeBase64(authStr.getBytes()); String authEncoded = new String(bytesEncoded); connection.setRequestProperty("Authorization", "Basic "+authEncoded); connection.setDoOutput(true); connection.setRequestMethod("POST"); OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());                     writer.write(param);  writer.close();

Samir

Avatar

Employee Advisor

Hi Samir, 

Yes, that is what I meant. You do not need to create the mycomponent in apps as you have already registered this resource type by binding it to the servlet. When you access any page which has this sling:resourceType then Sling will call the servlet automatically. You can restrict access to this page by either using CUG or ACLs. With this approach your servlet do not need to implement any custom authentication logic as it will be handled by AEM itself.  

Thanks,

Kunal

Avatar

Level 4

kunal23 wrote...

Hi Samir, 

Yes, that is what I meant. You do not need to create the mycomponent in apps as you have already registered this resource type by binding it to the servlet. When you access any page which has this sling:resourceType then Sling will call the servlet automatically. You can restrict access to this page by either using CUG or ACLs. With this approach your servlet do not need to implement any custom authentication logic as it will be handled by AEM itself.  

Thanks,

Kunal

 

Hi Kunal,

Thanks a lot for explaining in such detail man. With CUG it will redirect to  login page. But because I will be posting the data from within a webservice I will not need login page in response. 

Thanks,

Avatar

Employee Advisor

CUG just does a 302 redirect to any page you specify as path in the properties. It is not necessary that it should always be a login page. For example -You can have a redirect page which have "NOT PERMITTED" as output in the JSON format. 

Avatar

Employee Advisor

Also, if you use ACLs/permissions approach instead of CUG then you will get an error page with 403 response code in the header(if the passed user does not have permissions) and if it is successful then you will get 200 as response code in the header. In your service code you can check on the response header value to determine if the post was success or not.