Anyone?
> _____________________________________________ > From: [email protected] > [mailto:[email protected]] On Behalf Of Keith Garry Boyce > Sent: Friday, January 16, 2009 9:53 AM > To: [email protected] > Subject: CAS without CAS login page using restful api and > modifiedlogin-webflow.xml > > I wanted to code a JSF application where the login page is a JSF page > rather than a CAS page. I see this as a use case that cannot be overlooked > in present day application development. > > I understand that it is discouraged to present credentials to an > application but an applications security model shouldn't have to be custom > for every security solution plugged in. > > In my case I'm using spring security as the mechanism to glue the security > stuff together. If I switch from plain security to CAS security it seems > that all documentation points to me doing custom things for the login page > such as iframe etc.. > > So here's what I've come up with. I'd appreciate feedback on this > solution: > > In login-webflow.xml I made it so if ticketGrantingTicketId is passed as a > parameter on the /cas/login URL then > Service cookie can be issued directly using the ticketGrantingTicketId. In > my case I get the ticketGrantingTicketId using the CAS restful api. > > <action-state id="initialFlowSetup"> > <action bean="initialFlowSetupAction" /> > <!-- garpinc replace --> > <!-- > <transition on="success" > to="ticketGrantingTicketExistsCheck" /> > --> > <!-- garpinc with --> > <transition on="success" > to="ticketGrantingTicketIdExistsCheck" /> > <!-- garpinc end replace --> > </action-state> > > <!-- added by garpinc --> > <decision-state id="ticketGrantingTicketIdExistsCheck"> > <if test="${requestParameters.ticketGrantingTicketId == > null}" then="ticketGrantingTicketExistsCheck" > else="populateFromRequestParams" /> > </decision-state> > > <action-state id="populateFromRequestParams"> > <set attribute="ticketGrantingTicketId" > value="requestParameters.ticketGrantingTicketId" > scope="flow"/> > <transition on="success" to="sendTicketGrantingTicket" /> > </action-state> > <!-- end of garpinc add --> > > > Then I define a JSF controller. The pseudo steps are as follows > 1) username/password provided to jsf page > 2) adaptAuthenticationRequest is called to change this into an > Authentication CasAuthenticationProvider can process > 3) user is authenticated using provider > 4) to participate in SSO getFinalOutcome is called which redirects to > /cas/login with ticketGrantingTicketId and service which is page you want > to go to on successful login. > > public class CasAuthenticationController extends > AbstractAuthenticationController { > > private static final String CAS_TGR = "CAS_TGR"; > private ServiceProperties serviceProperties; > > public void setServiceProperties(ServiceProperties > serviceProperties) { > this.serviceProperties = serviceProperties; > } > > private String secureCasURL; > > public void setSecureCasURL(String secureCasURL) { > this.secureCasURL = secureCasURL; > } > > private String ticketURL; > > public void setTicketURL(String ticketURL) { > this.ticketURL = ticketURL; > } > > private boolean useCasSSO = true; > > public void setUseCasSSO(boolean useCasSSO) { > this.useCasSSO = useCasSSO; > } > > > protected void updateFacesContext(Authentication aut) { > > } > > > final protected String getFinalOutcome(String outcome) { > > if (outcome.equals("success") && useCasSSO) { > FacesContext ctx = > FacesContext.getCurrentInstance(); > ExternalContext extCtx = ctx.getExternalContext(); > > HttpServletRequest request = > (HttpServletRequest) extCtx.getRequest(); > String ticket = (String) > request.getAttribute(CAS_TGR); > > try { > extCtx.redirect( > secureCasURL > + "/login?service=" > + request.getScheme() + > "://" + request.getServerName() + ":" + request.getServerPort() + > request.getContextPath() > + > "/view/secure/facelet/content/home.iface&ticketGrantingTicketId=" + > ticket); > // this is ignored because extCtx.redirect > return "redirect"; > } catch (IOException e) { > throw new RuntimeException(e); > } > > } else { > return outcome; > } > } > > protected Authentication adaptAuthenticationRequest( > UsernamePasswordAuthenticationToken > usernamePasswordAuthenticationToken) throws Exception { > > HttpClient client = new HttpClient(); > > PostMethod post = new PostMethod(ticketURL); > NameValuePair[] usernamePasswordArray = { > new > NameValuePair("username",usernamePasswordAuthenticationToken.getPrincipal( > ).toString()), > new > NameValuePair("password",usernamePasswordAuthenticationToken.getCredential > s().toString()) > }; > post.setRequestBody(usernamePasswordArray); > int responseCode = client.executeMethod(post); > if (responseCode != 201) { > String body = post.getResponseBodyAsString(); > Pattern pattern = Pattern.compile(".*<h3>(.*)</h3>.*", > Pattern.DOTALL); > Matcher matcher = pattern.matcher(body); > if (matcher.matches()) { > String casError = matcher.group(1); > throw new AuthenticationServiceException(casError); > } else { > throw new RuntimeException("body does not contain an > error:" + body); > } > > } > String ticketGrantingResource = > post.getResponseHeader("Location").getValue(); > > Pattern pattern = Pattern.compile(".*\\/(.*)"); > Matcher matcher = pattern.matcher(ticketGrantingResource); > if (matcher.matches()) { > String ticketGrantingResourceToStore = matcher.group(1); > // Update cookie in browser for SSO > HttpServletRequest request = > (HttpServletRequest) > FacesContext.getCurrentInstance() > > .getExternalContext().getRequest(); > request.setAttribute(CAS_TGR, > ticketGrantingResourceToStore); > > } else { > throw new RuntimeException("ticketGrantingResource not in > right format:" + ticketGrantingResource); > } > > post = new PostMethod(ticketGrantingResource); > NameValuePair[] serviceArray = { > new > NameValuePair("service",serviceProperties.getService()), > }; > > post.setRequestBody(serviceArray); > responseCode = client.executeMethod(post); > if (responseCode != 200) { > throw new RuntimeException("response code was: " + > responseCode); > } > String ticket = post.getResponseBodyAsString(); > > return new UsernamePasswordAuthenticationToken( > CasProcessingFilter.CAS_STATEFUL_IDENTIFIER, > ticket); > > } > > > > } << File: ATT00037.txt >>
<<attachment: winmail.dat>>
_______________________________________________ Yale CAS mailing list [email protected] http://tp.its.yale.edu/mailman/listinfo/cas
