Jason,
I'll take a look at it later. I do want to point out though that you do
not need the custom BJUCredentialsToPrincipalResolver or
BJUCredentialsValidator . You can use the ones that come with CAS.
Also, your MetaDataPopulator shouldn't need to create a new
ImmutableAuthentication (newer versions of CAS use the MutableVersion
internally and then create a final Immutable version).
-Scott
Jason Tesser wrote:
> OK well I have it working for the most part. I do have one problem
> with my web-flow. It works if you are coming from an application but
> if you go directly to cas and login it doesn't send you to my
> gracelogin page. I tried to insert it into the web flow but when I
> tried to get the ticketid from something that doesn't have a service
> the ticketId is null. I will paste all my code below. 1 as a help to
> others 2. maybe someone can tell me what is up with the ticketId
>
> Had to make my own authHandler see below
>
> public class CASAuthProvider implements AuthenticationHandler,
> InitializingBean {
>
> private boolean authenticateUsernamePasswordInternal(
> BJUCredentials credentials) throws AuthenticationException {
> HashMap<String, Object> auth = EdirUtil.authenticate(credentials
> .getUsername(), credentials.getPassword());
> int result = ((Integer)
> auth.get(EdirUtil.LDAP_RESULT_KEY)).intValue();
>
> if (result == EdirUtil.SUCCESSFUL_LOGIN) {
> return true;
> } else if (result == EdirUtil.ACCOUNT_DISABLED) {
> throw new AccountDisabledException();
> } else if (result == EdirUtil.INVALID_PASSWORD) {
> throw new BadCredentialsAuthenticationException(
> "Login failed. Please check your credentials and
> try again.");
> } else if (result == EdirUtil.INVALID_USERNAME) {
> throw new BadUsernameOrPasswordAuthenticationException(
> "Login failed. Please check your credentials and
> try again.");
> } else if (result == EdirUtil.NO_MORE_GRACE_LOGINS) {
> throw new BlockedCredentialsAuthenticationException(
> "Login failed. You have used all your grace
> logins. Please contact the IT Helpdesk at ext. 3880.");
> } else if (result == EdirUtil.ON_A_GRACE_LOGIN) {
> getLog().info("Login successful but user is on a grace
> login");
> credentials.setOnGraceLogin(true);
> return true;
> } else {
> throw new BadCredentialsAuthenticationException();
> }
> }
>
> ... rest is like the UsernamePasswordAuthHandler
>
> The Credentials class
> public class BJUCredentials extends UsernamePasswordCredentials {
>
> /**
> *
> */
> private static final long serialVersionUID = 761960574486906106L;
>
> private boolean onGraceLogin;
>
> /**
> * @return Returns the onGraceLogin.
> */
> public boolean isOnGraceLogin() {
> return onGraceLogin;
> }
>
> /**
> * @param onGraceLogin The onGraceLogin to set.
> */
> public void setOnGraceLogin(boolean onGraceLogin) {
> this.onGraceLogin = onGraceLogin;
> }
> }
>
> public class BJUCredentialsToPrincipalResolver implements
> CredentialsToPrincipalResolver {
>
> /** Logging instance. */
> private final Log log = LogFactory.getLog(getClass());
>
> public Principal resolvePrincipal(Credentials credentials) {
> final BJUCredentials bjuCredentials = (BJUCredentials)
> credentials;
>
> if (log.isDebugEnabled ()) {
> log.debug("Creating SimplePrincipal for ["
> + bjuCredentials.getUsername() + "]");
> }
>
> return new SimplePrincipal(bjuCredentials.getUsername ());
> }
>
> public boolean supports(Credentials credentials) {
> return credentials != null
> && BJUCredentials.class.isAssignableFrom(credentials
> .getClass());
> }
>
> }
>
> public class BJUCredentialsValidator implements Validator {
>
> public boolean supports(final Class clazz) {
> return BJUCredentials.class.isAssignableFrom(clazz);
> }
>
> public void validate(final Object o, final Errors errors) {
> ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username",
> "required.username", null);
> ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password",
> "required.password", null);
> }
>
> }
>
> In spring I injected the objectName, objectClass, and validator to teh
> AuthenticatViaFormAction withthe above classes
>
> I also have a MetaDataPopulator
>
> public class MetaDataPopulator implements
> AuthenticationMetaDataPopulator {
>
> private Log log = LogFactory.getLog(this.getClass());
>
> public Authentication populateAttributes(Authentication auth,
> Credentials credentials) {
> HashMap<String, Boolean> attributes = new HashMap<String,
> Boolean>();
> log.info("Grace login attribute is false by default");
> attributes.put("isGraceLogin", false);
> if(((BJUCredentials)credentials).isOnGraceLogin()){
> log.info("Grace login attribute now set to true because
> the use is on a grace login");
> attributes.put("isGraceLogin", true);
> }
> return new
> ImmutableAuthentication(auth.getPrincipal(),attributes);
> }
> }
>
> Finally I made a CheckForGraceLoginAction
>
> public class CheckForGraceLoginAction extends AbstractLoginAction {
>
> private TicketRegistry ticketReg;
> private Log log = LogFactory.getLog(this.getClass());
>
> @Override
> protected Event doExecuteInternal(final RequestContext context,
> final String ticketGrantingTicketId, final String service,
> final boolean gateway, final boolean renew, final boolean
> warn) {
> ContextUtils.addAttribute(context, WebConstants.SERVICE ,
> service);
> log.info("Checking for grace login on ticketId = " +
> ticketGrantingTicketId);
> // Ticket ticket = ticketReg.getTicket(ticketGrantingTicketId);
> Ticket ticket = ticketReg.getTicket
> ((String)ContextUtils.getAttribute(context, WebConstants.TICKET));
> Map attributes =
> ticket.getGrantingTicket().getAuthentication().getAttributes();
> Boolean isGraceLogin = (Boolean)attributes.get("isGraceLogin");
> if(isGraceLogin){
> log.info("User is on a grace login so redirecting to grace
> login view to warn user.");
> return result("graceLogin");
> }
> return success();
> }
>
> /**
> * @return Returns the ticketReg.
> */
> public TicketRegistry getTicketReg() {
> return ticketReg;
> }
>
> /**
> * @param ticketReg The ticketReg to set.
> */
> public void setTicketReg(TicketRegistry ticketReg) {
> this.ticketReg = ticketReg;
> }
>
> }
>
> In the login-flow I set it up as follows
>
> <?xml version="1.0" encoding="UTF-8"?>
> <!DOCTYPE webflow PUBLIC "-//SPRING//DTD WEBFLOW//EN"
> "http://www.springframework.org/dtd/spring-webflow.dtd">
>
> <webflow id="loginFlow"
> start-state="ticketGrantingTicketExistsCheckAction">
> <action-state id="ticketGrantingTicketExistsCheckAction">
> <action bean="ticketGrantingTicketExistsAction" />
> <transition on="ticketGrantingTicketExists"
> to="hasServiceCheck" />
> <transition on="noTicketGrantingTicketExists"
> to="gatewayRequestCheck" />
> </action-state>
>
> <action-state id="gatewayRequestCheck">
> <action bean="gatewayRequestCheckAction" />
> <transition on="gateway" to="redirect" />
> <transition on="authenticationRequired" to="viewLoginForm" />
> </action-state>
>
> <action-state id="hasServiceCheck">
> <action bean="hasServiceCheckAction" />
> <transition on="authenticatedButNoService"
> to="viewGenericLoginSuccess" />
> <transition on="hasService" to="renewRequestCheck" />
> </action-state>
>
> <action-state id="renewRequestCheck">
> <action bean="renewRequestCheckAction" />
> <transition on="authenticationRequired" to="viewLoginForm" />
> <transition on="generateServiceTicket"
> to="generateServiceTicket" />
> </action-state>
>
> <!--
> <action-state id="startAuthenticate">
> <action bean="x509Check" />
> <transition on="success" to="sendTicketGrantingTicket" />
> <transition on="error" to="viewLoginForm" />
> </action-state>
> -->
> <view-state id="viewLoginForm" view="casLoginView">
> <transition on="submit" to="bindAndValidate" />
> </view-state>
>
> <action-state id="bindAndValidate">
> <action bean="authenticationViaFormAction" />
> <transition on="success" to="submit" />
> <transition on="error" to="viewLoginForm" />
> </action-state>
>
> <action-state id="submit">
> <action bean="authenticationViaFormAction" method="submit" />
> <transition on="warn" to="warn" />
> <transition on="success" to="sendTicketGrantingTicket" />
> <transition on="error" to="viewLoginForm" />
> </action-state>
>
> <action-state id="sendTicketGrantingTicket">
> <action bean="sendTicketGrantingTicketAction" />
> <transition on="success" to="serviceCheck" />
> </action-state>
>
> <action-state id="serviceCheck">
> <action bean="hasServiceCheckAction" />
> <transition on="authenticatedButNoService"
> to="viewGenericLoginSuccess" />
> <transition on="hasService" to="generateServiceTicket" />
> </action-state>
>
> <action-state id="generateServiceTicket">
> <action bean="generateServiceTicketAction" />
> <transition on="success" to ="warn" />
> <transition on="error" to="viewLoginForm" />
> <transition on="gateway" to="redirect" />
> </action-state>
>
> <!--
> The "warn" action makes the determination of whether to
> redirect directly to the requested
> service or display the "confirmation" page to go back to the
> server.
> -->
> <action-state id="warn">
> <action bean="warnAction" />
> <transition on="redirect" to="redirect" />
> <transition on="warn" to="showWarningView" />
> </action-state>
>
> <!--
> the "viewGenericLogin" is the end state for when a user
> attempts to login without coming directly from a service.
> They have only initialized their single-sign on session.
> -->
> <end-state id="viewGenericLoginSuccess"
> view="casLoginGenericSuccessView" />
>
> <!--
> The "showWarningView" end state is the end state for when the
> user has requested privacy settings (to be "warned") to be turned on.
> It delegates to a
> view defines in default_views.properties that display the
> "Please click here to go to the service." message.
> -->
> <end-state id="showWarningView" view="casLoginConfirmView" />
>
> <!--
> The "redirect" end state allows CAS to properly end the
> workflow while still redirecting
> the user back to the service required.
> -->
> <end-state id="redirect"
>
> view="class:org.jasig.cas.web.flow.RedirectViewDescriptorCreator" />
> </webflow>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Yale CAS mailing list
> [email protected]
> http://tp.its.yale.edu/mailman/listinfo/cas
>
_______________________________________________
Yale CAS mailing list
[email protected]
http://tp.its.yale.edu/mailman/listinfo/cas