0

Here is my problem:

Context : -Windows Server 2012 with ActiveDirectory -Tomcat -Rest API (Spring)

I'm currently trying to restrict REST request. I want that only specific groups of the AD could access to specific resources. I'm restricted to Kerberos authentication.

System configuration

  1. Create a user in domain "Tomcat"
  2. setspn -a HTTP/apirest.domain@DOMAIN
  3. Generate a tomcat.keytab using ktpass

API rest configuration

I'm using the spring security sample on github that you can find here :

https://github.com/spring-projects/spring-security-kerberos/tree/master/spring-security-kerberos-samples/sec-server-win-auth

I know that there is an EntryPoint and this is not needed in my context (API Rest). I've chosen this sample because it seems to use the windows authentication context and use it to automatically authenticate me in the spring security context. Right after, an ldap request is send to extract all information about the user logged. In my case, I need to extract the group.

I'm also using :

https://github.com/GyllingSW/kerberos-demo

To extract the role of the user with the class "RoleStrippingLdapUserDetailsMapper.java" instead of the "ActiveDirectoryLdapAuthoritiesPopulator". This implementation also offers localhost authentication but the issue with the NTLM token seems to be fixed in last commit of spring security.

I'm not really sure if this is the right way to do what I want.

My authentication seems to fail and I only have one things going wrong in my logs..

"Property 'userDn' not set - anonymous context will be used for read-write operations"

Questions

  1. Do I have to run my tomcat service using the tomcat account ? (Seems to be, yes)
  2. Am I doing the right things with Kerberos security ?
  3. How can I get rid of the anonymous context?
  4. The anonymous context seems to be set just right after Tomcat start. I want to get a context just after that my user (For instance, user1) requests the rest API (EntryPoint or whatever)

If there is something unclear let me know, I will try to reformulate!

Thanks,

csik
  • 43
  • 1
  • 4

2 Answers2

1

You do not need to query LDAP to get information about which groups does user belong to. Active Directory already adds this information to the Kerberos ticket which is sent from browser to Tomcat.

You just need to extract this information from the token for example using Kerb4J library. It comes with Spring integration inspired by spring-security-kerberos project so it should be pretty easy to switch to it.

If you still want to query LDAP you need to authenticate in LDAP before you can make any queries. Again there's no need to use end-user accounts for it - you can use the keytab file for Kerberos authentication in LDAP and query groups using "Tomcat" account

bedrin
  • 4,458
  • 32
  • 53
  • Thank you for your answer, I will try the solution with LDAP query to avoid importing one more dependency. This is strange that we cannot extract the group from the user token using spring-security (Using the native library). – csik Jun 04 '18 at 06:44
  • @csik Based on commits to github active development of spring-security-kerberos stopped 3 years ago, so it doesn't have many Kerberos features. Querying LDAP using your tomcat kerberos account should work though – bedrin Jun 04 '18 at 09:56
  • @bedrin - Do you have any sample code for using Kerb4j with Spring Security? – user8297969 Jan 18 '22 at 22:48
  • 1
    @user8297969 here's an example of Spring Security Configuration: https://github.com/bedrin/kerb4j/blob/0.1.2/kerb4j-server/kerb4j-server-spring-security/src/test/java/com/kerb4j/server/spring/integration/SpnegoAuthenticationProviderIntegrationTest.java#L159 - you will need to use ExtractGroupsUserDetailsService if you want to access groups information from Kerberos token: https://github.com/bedrin/kerb4j/blob/0.1.2/kerb4j-server/kerb4j-server-spring-security/src/main/java/com/kerb4j/server/spring/ExtractGroupsUserDetailsService.java – bedrin Jan 18 '22 at 23:04
  • @bedrin - Thanks. This is very helpful. I noticed that I get an error with my SPN name which is HTTP/myserver.mydomain.local@MYDOMAIN.LOCAL: `.AuthenticationServiceException: Invalid name provided (Mechanism level: Illegal character in realm name; one of: '/', ':', '^@' (600))`. I do not get an error with the old Spring Security Kerberos project. Do I need to change my SPN name? – user8297969 Jan 18 '22 at 23:55
  • @user8297969 please raise a GitHub issue with all the details – bedrin Jan 19 '22 at 12:20
  • @bedrin - GitHub issue raised with all the details. I simplified my code and I am now getting a checksum error instead. – user8297969 Jan 19 '22 at 19:56
  • @bedrin - Sorry for the additional note... The issue is located [here](https://github.com/bedrin/kerb4j/issues/39). I updated the issue with a [link](https://github.com/logicg8/kerb4j-vs-spring-security-kerberos) to complete example of the issue. – user8297969 Jan 20 '22 at 00:32
  • @user8297969 ok, thanks. I'll check within next few days – bedrin Jan 20 '22 at 07:59
  • @bedrin - I closed the issue as it was related to an old /etc/krb5.conf that kerb4j was referencing (but spring-security-kerberos was not). Once I removed the file, it worked. I'm now getting the group id(?) from the token. Is it possible to get the group name instead? I made a [SO question for this](https://stackoverflow.com/questions/70794587/kerb4j-how-to-get-role-name-from-spnego-token). – user8297969 Jan 21 '22 at 16:13
0

I found a way to fix my issue.

In a REST API context, you have no entry point. I tried to set my entry point to an unmapped URL, just to do the negociation. By doing this, you will receive an HTTP response with the error code 404 (Not found) but with the right header was added by spring security (WWW-Authenticate).

The web browser will not send the ticket service if the error code is not 401.

To solve this problem, you have to create a CustomEntryPoint class (implements AuthenticationEntryPoint) and you need to override the "commence" method to return a 401 HTTP code with the right header.

I hope that could help. If there is a better way, let me know !

csik
  • 43
  • 1
  • 4