Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Access to your application begins when the user calls for a CAS login including the application URL or service needed. This looks very much like this.

Code Block

http(s)://cas_server/cas/login?service=http(s)://other_server/application1

When the CAS server receives the request, CAS programmatically CAS authenticates the user either via prompting the user to login or by checking to see if they already have an active SSO session with CAS (Ticket Granting Ticket, TGT). If authentication is successful, CAS generates a service ticket (ST) and programmatically forms a new URL request (redirection) and calls application1 and adds a unique one-time-only random ticket (String) as a request parameterwith the ST as a request parameter in the query string. Remember that the user does not see any of this. Also, please note that HTTPS is marked with parentheses. It is critical that you understand how HTTPS can be used. CAS will make no assumptions outside of the authentication security mechanism. HTTPS recommendations and practices will be discussed in separate documentation.

Code Block

http(s)://other_server/application1?ticket=ST-8670-123buTvFFjo980

The other server receives this request through a CAS client (either a servlet filter or a module) that's been configured with application1. It parses the ticket and starts a new HTTPS connection with the CAS server. This new request is formed programmatically by the CAS filter Java code and it's commonly called the "service validation" step. It receives an SSL certificate after it sends a request to the CAS server. By protocol and Java standard, the certificate is compared by Java to it's collection of trusted certificates. If the certificate is "trusted", the HTTPS communication will occur.

CAS receives this secure request and prompts the user for his password. This is where the CAS server authenticates the user that's requesting access to application1. Remember that all this is occurring and the user has only made a single request to access application1. CAS will also verify server-to-server request, verifies that application1 has been loaded into it's persistent store of CAS registered services. It is, so CAS presents an HTML login screen to the user. The user enters his credentials and CAS will do the verification.Once the user has been authenticated, the CAS server fulfills the and if successful, fulfills the application server's HTTPS CAS client request and returns an XML message of "success" along with the authenticated username. The original request exits then passes though the CAS filter/module and now allows application1 to serve content to this newly authenticated user.

...

The user first makes a request to the CAS server for login and access to one of the CAS registered services.

Code Block

http://cas_server/cas/login?service=http://other_server/application1

...

Code Block
titleGenerateServiceTicketAction.java (CAS Server)
borderStylesolid

public final class GenerateServiceTicketAction extends AbstractAction {
    
    /** Instance of CentralAuthenticationService. */
    @NotNull
    private CentralAuthenticationService centralAuthenticationService;

    protected Event doExecute(final RequestContext context) {
        final Service service = WebUtils.getService(context);
        final String ticketGrantingTicket = WebUtils.getTicketGrantingTicketId(context);

        try {
            final String serviceTicketId = this.centralAuthenticationService
                .grantServiceTicket(ticketGrantingTicket,
                    service);
            WebUtils.putServiceTicketInRequestScope(context,
                serviceTicketId);
            return success();
        } catch (final TicketException e) {
            if (isGatewayPresent(context)) {
                return result("gateway");
            }
        }

        return error();
    }
 ...

...

Code Block
titleDynamicRedirectViewSelector.java (CAS Server)
borderStylesolid

public final class DynamicRedirectViewSelector implements ViewSelector {

    public ViewSelection makeRefreshSelection(final RequestContext context) {
        return makeEntrySelection(context);
    }

    public boolean isEntrySelectionRenderable(final RequestContext request) {
        return false;
    }

    public ViewSelection makeEntrySelection(final RequestContext request) {
        final WebApplicationService service = WebUtils.getService(request);
        final String ticket = WebUtils.getServiceTicketFromRequestScope(request);
        final Response serviceResponse = service.getResponse(ticket);
            
        switch (serviceResponse.getResponseType()) {
            case POST:
                final Map<String, Object> model = new HashMap<String, Object>();
                model.put("parameters", serviceResponse.getAttributes());
                model.put("originalUrl", service.getId());
                return new ApplicationView("postResponseView", model);
                
            default:
                return new ExternalRedirect(service.getResponse(ticket).getUrl());
        }
    }
}

...

Code Block
titleCASFilter.java (CAS Client)
borderStylesolid

...
    private String getAuthenticatedUser(HttpServletRequest request)
        throws ServletException {
        ProxyTicketValidator pv = null;
        try {
            pv = new ProxyTicketValidator();
            pv.setCasValidateUrl(casValidate);
            pv.setServiceTicket(request.getParameter("ticket"));
            pv.setService(getService(request));
	    pv.setRenew(Boolean.valueOf(casRenew).booleanValue());
            pv.validate();
            if (!pv.isAuthenticationSuccesful())
                throw new ServletException(
                    "CAS authentication error: " + pv.getErrorCode() + ": " + pv.getErrorMessage());
            if (pv.getProxyList().size() != 0) {
                // ticket was proxied
                if (casAuthorizedProxy == null) {
                    throw new ServletException("this page does not accept proxied tickets");
                } else {
                    boolean authorized = false;
                    String proxy = (String)pv.getProxyList().get(0);
                    StringTokenizer casProxies =
                        new StringTokenizer(casAuthorizedProxy);
                    while (casProxies.hasMoreTokens()) {
                        if (proxy.equals(casProxies.nextToken())) {
                            authorized = true;
                            break;
                        }
                    }
                    if (!authorized) {
                        throw new ServletException(
                            "unauthorized top-level proxy: '"
                                + pv.getProxyList().get(0)
                                + "'");
                    }
                }
            }
            return pv.getUser();
        } catch (SAXException ex) {
            String xmlResponse = "";
            if (pv != null)
                xmlResponse = pv.getResponse();
            throw new ServletException(ex + " " + xmlResponse);
        } catch (ParserConfigurationException ex) {
            throw new ServletException(ex);
        } catch (IOException ex) {
            throw new ServletException(ex);
        }
    }

...

...

Code Block
titleServiceTicketValidator.java (CAS Client)
borderStylesolid

...
  public void validate()
      throws IOException, SAXException, ParserConfigurationException {
    if (casValidateUrl == null || st == null)
      throw new IllegalStateException("must set validation URL and ticket");
    clear();
    attemptedAuthentication = true;
    StringBuffer sb = new StringBuffer();
    sb.append(casValidateUrl);
    if (casValidateUrl.indexOf('?') == -1)
      sb.append('?');
    else
      sb.append('&');
    sb.append("service=" + service + "&ticket=" + st);
    if (proxyCallbackUrl != null)
      sb.append("&pgtUrl=" + proxyCallbackUrl);
    if (renew)
      sb.append("&renew=true");
    String url = sb.toString();
    String response = SecureURL.retrieve(url);
    this.entireResponse = response;

    // parse the response and set appropriate properties
    if (response != null) {
      XMLReader r =
        SAXParserFactory.newInstance().newSAXParser().getXMLReader();
      r.setFeature("http://xml.org/sax/features/namespaces", false);
      r.setContentHandler(newHandler());
      r.parse(new InputSource(new StringReader(response)));
    }
  }
...

...