CAS Proxy Authentication
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?
@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?
@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.
I don't see anything wrong. Do you have some sample project to let me dig on problem?
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://.*"
}
}
@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
@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:
- How work on my develop machine? Or remote debug is the only option? This problem is priopity.
- 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.