CAS 3 Ticket Domain Model
This page is a place to evolve a CAS 3 domain model for tickets.
Legacy page
The content in this page is outdated. See instead Ticket module.
Discussion
The question we're asking is, "What's the proper relationship, in a class hierarchy used by CAS server implementation, between service tickets and proxy tickets?"
Code snippets
Ticket
public Interface Ticket {
/**
* Get the Date at which this Ticket was created.
*/
public Date getTimestamp();
/**
* Returns true if this ticket is valid, false otherwise.
*/
public boolean isValid();
}
TicketGrantingTicket
public Interface TicketGrantingTicket
extends Ticket {
/**
* Get the Principal which owns this TicketGrantingTicket and may exercise it
* to obtain a TargettedTicket for authentication to a particular URL.
* For instance, in the case of a SSOTicket this Principal is the end user who authenticated
* to CAS by presentation of Primary Credentials.
* In the case of a ProxyGrantingTicket, this is the URL to which the PGT was vended.
*/
public Principal getPrincipal();
/**
* Derive from this TicketGrantingTicket a TargettedTicket for use in authenticating
* to some particular target.
*/
public TargettedTicket deriveTicket(URL target);
}
ProxyGrantingTicket
public Class ProxyGrantingTicket
implements TicketGrantingTicket, DerivedTicket {
private final Date whenCreated = new Date();
private final Principal authenticatedUser;
private final ExpirationPolicy expPolicy;
private final ExpirationPolicyFactory expPolicyFactory;
private final TicketGrantingTicket parent;
public ProxyGrantingTicket(Principal proxyingService,
ExpirationPolicy expPolicy,
ExpirationPolicyFactory expPolicyFactory,
TicketGrantingTicket parent) {
this.authenticatedUser = authenticatedUser;
this.expPolicy = expPolicy;
this.expPolicyFactory = expPolicyFactory;
this.parent = parent;
}
public Principal getUser() {
return this.authenticatedUser;
}
public boolean isValid() {
return this.expPolicy.isValid();
}
public void expire() {
this.expPolicy.expire();
}
public TargettedTicket deriveTicket(URL target) {
return new TargettedTicketImpl(target, this, this.expPolicyFactory.buildPolicyInstance());
}
public TicketGrantingTicket getParant() {
return this.parent;
}
}
DerivedTicket
public Interface DerivedTicket
extends Ticket {
/**
* Get the TicketGrantingTicket from which this ticket was derived.
*/
public TicketGrantingTicket getParent();
}
TargettedTicket
public Interface TargettedTicket
extends DerivedTicket {
/**
* Get the URL to which this ticket will authenticate.
*/
public URL getTarget();
/**
* Get the chain of principals through which authentication has passed
* in producing this targetted ticket, starting with the most recent principal
* and leading back to the originally authenticating User.
*/
public List getPrincipalChain();
}
TargettedTicketImpl
public Class TargettedTicketImpl implements TargettedTicket {
private final Date whenCreated = new Date();
private final ExpirationPolicy expPolicy;
private final TicketGrantingTicket parent;
private final URL target;
public SSOTicket(URL target, TicketGrantingTicket parent, ExpirationPolicy expPolicy) {
this.target = target;
this.parent = parent;
this.expPolicy = expPolicy;
}
public boolean isValid() {
return this.expPolicy.isValid()
&& this.parent.isValid();
}
public URL getTarget() {
return this.target;
}
public List getPrincipalChain() {
List principalChain = new ArrayList();
TicketGrantingTicket ancestor = this.parent;
while (ancestor != null) {
principalChain.add(ancestor.getPrincipal());
if (parent instanceof DerivedTicket) {
DerivedTicket ancestorIsAlsoAChild = (DerivedTicket) ancestor;
ancestor = ancestor.getParent();
} else {
// perhaps an ugly way of breaking out of this while loop
ancestor = null;
}
}
return principalChain;
}
public TicketGrantingTicket getParent() {
return this.parent;
}
}