My application was developed using wicket and integrated with keycloak 10.0.2.
I have an issue with the redirect_uri, it is always in http (like https://id.dev.subok.com/auth/realms/subok/protocol/openid-connect/auth? ... &redirect_uri=http%3A%2F%2Ftest.subok.com%2F ....
To elaborate:
When I try to access my app via https://test.subok.com, I am expecting that the redirect_uri will be https%3A%2F%2Ftest.subok.com%2F but it was http%3A%2F%2Ftest.subok.com%2F. The redirect_uri is always http even if I use http or https.
The way I integrate Keycloak to my application is via servlet filter:
POM
...
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-servlet-filter-adapter</artifactId>
<version>10.0.2</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-client</artifactId>
<version>10.0.2</version>
</dependency>
...
web.xml
...
<filter>
<filter-name>keycloak</filter-name>
<filter-class>org.keycloak.adapters.servlet.KeycloakOIDCFilter</filter-class>
<init-param>
<param-name>keycloak.config.skipPattern</param-name>
<param-value>/((error-page.html)|(access-denied-page.html))</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>keycloak</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
Is there a way to override the value of generated redirect_uri? Specifically to use https if the request is https and http if the request is http. Or just use https redirect_url for both http and https request?
Am using Jersey 1.19 for a REST service..
The URL pattern in web.xml is:
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
In the Java class am using a method which is doing a kind of redirect to another page saved in a web folder. It looks fine up to the point when I call a specific resource:
http://localhost:8084/userProfile/rest/user
This should redirect to:
http://localhost:8084/userProfile/signup/index.jsp
but it redirects to:
http://localhost:8084/userProfile/rest/signup/index.jsp
Which normally doesn't exist.
The method in the Java Class:
#Path("/user")
public class userProfile {
#GET
#Produces(MediaType.TEXT_HTML)
public Response returnForm() throws URISyntaxException {
URI uri = new URI("/signup/index.jsp");
return Response.temporaryRedirect(uri).build();
}
}
How can I avoid redirection to a URL including /rest/?
The solution is/was really simple... the Path should go one step back to
avoid the url-pattern /rest/*:
....
URI uri = new URI("../signup/index.jsp");
...
Thx!
I followed this tutorial to enable REST service on my local CAS server.
However there is no Java example
"Java REST Client Example
We need a real, working, example, the previous one is useless. Many people are emailing me that it is not working, and I confirm it does not work."
I was able to find this but that unfortunately did not work for me.
Any pointers/links? Much appreciated.
Got it!
Here is the complete solution on how to enable CAS REST API and be able to connect to it via JAVA REST client to benefit others
Get CAS source code.
Review this article
Add following to pom.xml like suggested by the article in #2
<dependency>
<groupId>org.jasig.cas</groupId>
<artifactId>cas-server-integration-restlet</artifactId>
<version>${cas.version}</version>
<type>jar</type>
</dependency>
Make sure to add following to pom.xml to avoid Spring jar collisions. In my case, cas-server-integration-restlet was dependent on spring-web, which used by default older version of Spring. So, I explicitly defined
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
Compile your cas code. Should get cas.war in your target folder.
Upload it to your server, change permissions to tomcat and wait for it to get deployed
In CATALINA/conf find server.xml and uncomment 8443 port configuration so that our sever will allow SSL connections. Also, specify your certs in here.
Now navigate to exploded cas.war file and drill down to WEB-INF folder to find deployerConfigContext.xml file. Specify what CAS would use to authenticate. In my case, I used LDAP.
Add following to web.xml per article above
<servlet>
<servlet-name>restlet</servlet-name>
<servlet-class>com.noelios.restlet.ext.spring.RestletFrameworkServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>restlet</servlet-name>
<url-pattern>/v1/*</url-pattern>
</servlet-mapping>
Restart tomcat for changes to take effect.
Test that you can log in via standard CAS UI: https://server:8443/cas/login
Test that REST API was exposed via: https://server:8443/cas/v1/tickets
Now let's connect to it. I used this sample code. Make sure to give correct links and username/password
When I tried running the code as is, it complained about "Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target". Basically asking you to install certs. If you have the access to the server, just copy it over. If not, I found this code that will take care of the installation for you if you dont have access or just too lazy :)
Now, if you run the JAVA CAS Client with valid credentials you should see something like
201
https://server_name:8443/cas/v1/tickets/TGT-4-rhVWLapYuOYi4InSEcmfNcABzaLMCPJgGIzlKqU1vb50zxb6pp-server_name
Tgt is : TGT-4-rhVWLapYuOYi4InSEcmfNcABzaLMCPJgGIzlKqU1vb50zxb6pp-server_name.ndev.coic.mil
Service url is : service=https%3A%2F%2Fmyserver.com%2FtestApplication
https://server_name:8443/cas/v1/tickets/TGT-4-rhVWLapYuOYi4InSEcmfNcABzaLMCPJgGIzlKqU1vb50zxb6pp-server_name
Response code is: 200
200
ST-4-BZNVm9h6k3DAvSQe5I3C-server_name
You can see 200 code and the ticket. If you were to review logs of your cas on the server, you should see messages about successful athentication and ticket generation.
Change username/password to some dummy data and try to run the code. You will get 400 error message, which means that permission to access was denied.
Success!
For CAS 4.0 it's a little simpler (tested on apache-tomcat-7.0.55)
in your pom.xml add following dependency
<dependency>
<groupId>org.jasig.cas</groupId>
<artifactId>cas-server-integration-restlet</artifactId>
<version>4.0.0</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
Direct dependency to springframework is not necesarry because exclusions prevent from duplicated packages
In your web.xml you need to add servlet mapping for restlet (mind package has changed from com.noelios.restlet... to org.restlet...
<servlet>
<servlet-name>restlet</servlet-name>
<servlet-class>org.restlet.ext.spring.RestletFrameworkServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>restlet</servlet-name>
<url-pattern>/v1/*</url-pattern>
</servlet-mapping>
As a result of above steps in yuor WEB-INF/lib directory following new files should be added
ls target/cas/WEB-INF/lib/ | grep restlet
cas-server-integration-restlet-4.0.0.jar
org.restlet-2.1.0.jar
org.restlet.ext.servlet-2.1.0.jar
org.restlet.ext.slf4j-2.1.0.jar
org.restlet.ext.spring-2.1.0.jar
If you wish to skip cert validation add this to your Java Client
//////////////////////////////////////////////////////////////////////////////////////
// this block of code turns off the certificate validation so the client can talk to an SSL
// server that uses a self-signed certificate
//
// !!!! WARNING make sure NOT to do this against a production site
//
// this block of code owes thanks to http://www.exampledepot.com/egs/javax.net.ssl/trustall.html
//
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType){}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType){}
}
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
//
//
// end of block of code that turns off certificate validation
// ////////////////////////////////////////////////////////////////////////////////////
Usually devs are confused on how to get rest client working when accessing secured CAS web service. Most of the question out there were asking how to get restlet CAS secures a webservice and how to call those web service, because no real example were working.
Well actually there is. Groovy example is on the JASIG Cas restlet example https://wiki.jasig.org/display/casum/restful+api is clearly show how to get authenticated to call a service (its using Groovy, but converting to Java should be straight forward) . But in my opinion, it do not clearly explain that client need to authenticate to the designated web service first before accessing CAS secured web service.
For example, assume there is a JSON service that secured with CAS and build with Java and Spring. And you are using code that describe on the groovy section on https://wiki.jasig.org/display/casum/restful+api
String casUrl="https://yourcas.com/v1/tickets"
String springTicketValidation="http://yourservice.com/j_spring_cas_security_check"
String serviceToCall="http://yourservice.com/serviceToCall"
To get your service client be able to call the service, you need to follow these simple rules:
Get your ticket granting ticket from CAS
Get your Service Ticket from cas for the designated service call (service to call)
Authenticate to your service ticket validator (at this point url specified on springTicketValidation)
finally call your service
or in code perspective
String ticketGrantingTicket = getTicketGrantingTicket(casUrl, username, password)
String serviceTicket = client.getServiceTicket(casUrl, ticketGrantingTicket, serviceToCall)
// validate your ticket first to your application
getServiceCall(springTicketValidation, serviceTicket)
getServiceCall(serviceToCall, serviceTicket)
And for your note, all these operation should be done in following condition:
Your call (both restlet call and service call) should be done in the same HttpClient object. It seems that CAS put "something" in the session object that validated when you call your service. Fails this, and you will always get logon page on the HTTP result.
Your cas client should be able to recognized your CAS SSL certificate, otherwise it will throw you PKIX path building failed
This example is based on the cas secured web service that using Spring Security to secured service with CAS. I'm not sure whether other cas secured should need ticket validation on the application side or not
Hope this help
I have pretty simple web-service, which runs on the Embedded Glassfish server:
#Stateless
#Path("/id")
#Produces(MediaType.TEXT_HTML)
public class SimpleFacadeBean {
#GET
public String sayHello(#Context HttpServletRequest request, #Context HttpServletResponse response) {
return "Hello world!";
}
}
And corresponding class, that set root-element for all web-service calls:
#ApplicationPath("root")
public class ApplicationConfig extends Application {
}
Everything works fine, but I want to protect this GET method through SSL.
I have read such manuals as: this, and this. I am not interested in configuring Glassfish part of SSL connection (I know how to do it), I just want not to see my GET method in localhost:8080/root/application.wadl link (this will mean that my web-service is connected to 8181 secure glassfish port, not to default unsecure 8080 port).
For this purpose I wrote web.xml descriptor and put it in webapp/WEB-INF directory. The most interesting part of it looks like:
<security-constraint>
<display-name>SecurityConstraint</display-name>
<web-resource-collection>
<web-resource-name>Secure Area</web-resource-name>
<url-pattern>/root/id</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
But after executing I saw (in application.wadl) again my web-service URL connected to unsecured port (8080 instead of 8181). I have tried a lot of other ways, trying to make my code work correctly. I was not successful at all.
I package this web-services into .war. After that this .war goes to .ear. Any ideas why I am not successful in NOT seeing my "secure" web-service in application.wadl?
I want to pass a security context to my rest service.
On server side I try to get this with:
public Response postObject(#Context SecurityContext security, JAXBElement<Object> object) {
System.out.println("Security Context: " + security.getUserPrincipal());
.....
But actually the Syso is null.
On Client side im just doing:
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
client.addFilter(new HTTPBasicAuthFilter("user", "password"));
So, do I have to change in addition something in my web.xml to get it working?
I hoped its working without setting up static users in the tomcat user xml. So I can compare the user/password from security context with my "persistent" user/password hashmap located server sided. But when it is not working without tomcat user xml, how can it be done to add dynamically user to that user xml? When I ve static users I cant register a new user. I dont want to use this attempt: http://objecthunter.congrace.de/tinybo/blog/articles/89 cuz I want just to work with a semi persistence like a HashMap of user/password.
Besides another question: Why does everybody refer to Apache HttpClient when it is about security in Jersey, when it is working like I wrote as well?
My attempt refers to this post:
Jersey Client API - authentication
You need to set up your application on the server so that it requires Basic authentication. I.e. include something like the following in the web.xml in your application war file - otherwise Tomcat does not perform the authentication and does not populate the security context.
<security-constraint>
<display-name>Authentication Constraint</display-name>
<web-resource-collection>
<web-resource-name>all</web-resource-name>
<description/>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description>authentication required</description>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>realm_name</realm-name>
</login-config>