Search code examples
javaspringsecurityauthenticationcas

Spring Security with CAS rest (Direct login)


I have a question about using Spring CAS Service. Everything is working so far. (Server & Client)

But I need to authenticate without the redirect to the cas login site. So I need a direct login, to request some data from the service API.

I added the CAS Rest authentification to my cas server.

And now I can request a TGT ticket via:

curl --data "username=demo&password=demo" https://cas/cas/v1/tickets

After that, I can request a service ticket via TGT Ticket:

curl --data "service=https://serviceHost/web/" https://cas/cas/v1/tickets/TGT-9-ODzpFwQF7dwxSrtCPkR3ZySfnMroyp

I see in the CAS Server logs, the user is authendicated with this service ticket.

But when I try to request some URL from my service via:

curl https://serviceHost/web/api/getAuftraege?ticket=ST-21-4ucWgqnFTSyYT

I am redirected to the cas login site.

I think my webapp is not interpreting my "ticket" param.

Do I have to put some kind of resolver into the config of my webapp?

Do I need some dependencies for my Spring web Application?


Solution

  • 2 years ago I had a task that I should wrote a java client for cas login:

    public boolean login(String service, String jsessionid) throws IOException {
        tgt = getTicketGrantingTicket(username, password);
        String st = getServiceTicket(service, tgt);
        commitJsessionid(service, jsessionid, st);
        this.jsessionid = jsessionid;
        return true;
    }
    
    public String getTicketGrantingTicket(String username, String password) throws IOException {
        Map<String, Object> params = new LinkedHashMap<>();
        params.put("username", username);
        params.put("password", password);
        HttpURLConnection conn = restClient.post(casUrl + "/v1/tickets", params);
        StringBuilder responseBuilder = new StringBuilder();
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        String input;
        while ((input = in.readLine()) != null) {
            responseBuilder.append(input);
        }
        in.close();
    
        String response = responseBuilder.toString();
        if (conn.getResponseCode() == 400) {
            throw new AuthenticationException("bad username or password");
        }
        String location = conn.getHeaderField("Location");
        return location;
    }
    
    public String getServiceTicket(String service, String tgt) throws IOException {
        Map<String, Object> params = new LinkedHashMap<>();
    
        params.put("service", service + "/j_acegi_security_check");
    
        HttpURLConnection conn = restClient.post(tgt, params);
        StringBuilder responseBuilder = new StringBuilder();
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        String input;
        while ((input = in.readLine()) != null) {
            responseBuilder.append(input);
        }
        in.close();
    
        String response = responseBuilder.toString();
    
        return response;
    }
    
    public String commitJsessionid(String service, String jsessionid, String st) throws IOException {
        HttpURLConnection conn = restClient.get(service + "/j_acegi_security_check;jsessionid=" + jsessionid + "?ticket=" + st);
        StringBuilder responseBuilder = new StringBuilder();
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        String input;
        while ((input = in.readLine()) != null) {
            responseBuilder.append(input);
        }
        in.close();
    
        String response = responseBuilder.toString();
    
        return response;
    }
    
    public boolean validateServiceTicket(String service, String st) throws IOException {
        HttpURLConnection conn = restClient.get(casUrl + "/proxyValidate?ticket=" + st + "&service=" + service + "/j_acegi_security_check");
        StringBuilder responseBuilder = new StringBuilder();
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        String input;
        while ((input = in.readLine()) != null) {
            responseBuilder.append(input);
        }
        in.close();
    
        String response = responseBuilder.toString();
    
        return response.toString().contains("authenticationSuccess");
    }
    

    and you can call your rest service with this method:

        public String callRestExample(String service, String rest) throws IOException {
        String url = service;
        if (jsessionid != null)
            url += "/services/" + rest + ";jsessionid=" + jsessionid;
    
        HttpURLConnection conn = restClient.get(url);
        StringBuilder responseBuilder = new StringBuilder();
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        String input;
        while ((input = in.readLine()) != null) {
            responseBuilder.append(input);
        }
        in.close();
    
        String response = responseBuilder.toString();
        if (jsessionid == null) {
            int index = response.indexOf("jsessionid");
            jsessionid = response.substring(index + 13, index + 45);
            tgt = getTicketGrantingTicket(username, password);
            String st = getServiceTicket(service, tgt);
            commitJsessionid(service, jsessionid, st);
            callRestExample(service, rest);
        }
    
        return response;
    }