kakawait / cas-security-spring-boot-starter

Spring boot starter for Apereo CAS client fully integrated with Spring security
MIT License
152 stars 45 forks source link

CAS Proxy Authentication #156

Open kulemeevag opened 3 years ago

kulemeevag commented 3 years ago

Hello!

Try to implement proxy authentication.

I have Apereo CAS Server on another machine in my network. In my app(on my local machine) i use your starter(v.1.0.6). My config is:

security:
  cas:
    server:
      base-url: https://cas.my-domain.ru/cas/
    service:
      resolution-mode: dynamic
      paths:
        proxy-callback: http://my_local_machine_IP:8081/casCallback

casCallback method is:

    @GetMapping(path = "/casCallback")
    public void casCallback(@RequestParam(name = "pgtIou") final String proxyGrantingTicketIou, @RequestParam(name = "pgtId") final String proxyGrantingTicket) {
        proxyGrantingTicketStorage.save(proxyGrantingTicketIou, proxyGrantingTicket);
    }

I create bean with interceptor for RestRemplate(used from documentation):

    @Bean
    RestTemplate casRestTemplate(ServiceProperties serviceProperties, ProxyTicketProvider proxyTicketProvider) {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getInterceptors().add(new CasAuthorizationInterceptor(serviceProperties, proxyTicketProvider));
        return restTemplate;
    }

When i send request to another app with my casRestTemplate i have:

{
  "timestamp": "2021-04-27T04:02:23.547+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "Proxy ticket provider returned a null proxy ticket for service http://my-another-app",
  "path": "/api/same-url"
}

Cas Specification says that CAS server send request to cas callback url. But my cas callback method was not called.

But in my app log i see that i have *proxyGrantingTicket: PGTIOU-71-**cas* from CAS Server response. In debug mode i found in ProxyGrantingTicketStorage cache is empty. And ProxyGrantingTicketStorage return null ProxyGrantingTicket.

What am I doing wrong? Maybe you need to set something else in the configs? Or add some beans? Maybe I wrong undestand cas specification for proxy?

kakawait commented 3 years ago

@kulemeevag you should not define your own endpoint

@GetMapping(path = "/casCallback")
    public void casCallback(@RequestParam(name = "pgtIou") final String proxyGrantingTicketIou, @RequestParam(name = "pgtId") final String proxyGrantingTicket) {
        proxyGrantingTicketStorage.save(proxyGrantingTicketIou, proxyGrantingTicket);
    }

because is already managed by a CAS filter

Can you please retry without?

kulemeevag commented 3 years ago

@kakawait, indeed there is no need to implement an endpoint. I remove implementation for casCallback and received proxyGrantingTicket:PGTIOU-74-****cas. But ProxyGrantingTicketStorage cache is still empty.

kakawait commented 3 years ago

I don't see anything wrong. Do you have some sample project to let me dig on problem?

kulemeevag commented 3 years ago

I don't see anything wrong. Do you have some sample project to let me dig on problem?

Created sample repository. But unfortunately I can't provide the CAS Server.

CAS Server (v.5.2.6) registered service from JSON file:

{
  "@class" : "org.apereo.cas.services.RegexRegisteredService",
  "serviceId" : "^(http)://.*",
  "name" : "All",
  "id" : 10000001,
  "description" : "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
  "evaluationOrder" : 10000,
  "proxyPolicy" : {
    "@class" : "org.apereo.cas.services.RegexMatchingRegisteredServiceProxyPolicy",
    "pattern" : "^http://.*"
  }
}
kakawait commented 3 years ago

@kulemeevag proxy call back setting must be a path, otherwise it will fail because of https://github.com/spring-projects/spring-security/blob/main/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java#L293

If you add url that will generate ant path /**http://my_local_machine_IP:8081/casCallback that will not works as expected

Can you please try with

security:
  cas:
    server:
      base-url: https://cas.my-domain.ru/cas/
    service:
      resolution-mode: dynamic
      paths:
        proxy-callback: /casCallback

if not work I may spotted a bug when path is not defined, so please try

security:
  cas:
    path: /,/api/**
    server:
      base-url: https://cas.my-domain.ru/cas/
    service:
      resolution-mode: dynamic
      paths:
        proxy-callback: /casCallback
kulemeevag commented 3 years ago

@kakawait, thanks for your answer.

I did this before your answer. Deploy 2 war to Tomcat on my server. On server app generate proxy ticket. This code work fine:

proxyTicketProvider.getProxyTicket("url")

But then I send request from first app to second app in response I see 401 error. If I added this properties to my application.yml:

proxy-validation:
  chains:
    - http://my-server:8080/myApp/cas/proxy-callback

Then proxy flow work fine. This my properties:

security:
  cas:
    server:
      base-url: https://cas.my-domain.ru/cas/
    service:
      resolution-mode: dynamic
      paths:
        proxy-callback: /cas/proxy-callback
    proxy-validation:
      chains:
        - http://my-server:8080/myApp/cas/proxy-callback

Now i have 2 problems:

  1. How work on my develop machine? Or remote debug is the only option? This problem is priopity.
  2. If set proxy validation chains: http://my-server:8080/myApp I have 401 error. In log file from second app I see:
    2021-05-13 10:27:03.365  WARN 21904 --- [http-nio-8081-exec-502] o.jasig.cas.client.validation.ProxyList  : Proxy chain did not match at http://my-server:8080/myApp/cas/proxy-callback. Skipping to next allowedProxyChain
    2021-05-13 10:27:03.365  WARN 21904 --- [http-nio-8081-exec-502] o.jasig.cas.client.validation.ProxyList  : No proxy chain matched the allowedProxyChains list.
    2021-05-13 10:27:03.365  WARN 21904 --- [http-nio-8081-exec-502] o.j.c.c.v.Cas30ProxyTicketValidator      : Proxies received from the CAS validation response are [http://my-server:8080/myApp/cas/proxy-callback]. However, none are allowed by allowed proxy chain of the client which is [[org.jasig.cas.client.authentication.RegexUrlPatternMatcherStrategy@758aa924]]

    I want to set only one url for domain. And do not specify app name on Tomcat and proxy callback name.