def validate_ticket(self, ticket, service): """ Given a ticket string and service identifier, validate the corresponding ``Ticket``. If validation succeeds, return the ``Ticket``. If validation fails, raise an appropriate error. """ if not ticket: raise InvalidRequest("No ticket string provided") if not service: raise InvalidRequest("No service identifier provided") if not self.model.TICKET_RE.match(ticket): raise InvalidTicket("Ticket string %s is invalid" % ticket) try: t = self.get(ticket=ticket) except self.model.DoesNotExist: raise BadPgt("Ticket %s does not exist" % ticket) if t.is_consumed(): raise InvalidTicket("%s %s has already been used" % (t.name, ticket)) if t.is_expired(): raise InvalidTicket("%s %s has expired" % (t.name, ticket)) if not is_valid_service_url(service): raise InvalidService("Service %s is not a valid %s URL" % (service, t.name)) logger.debug("Validated %s %s" % (t.name, ticket)) return t
def validate_ticket(self, ticket, service, renew=False, require_https=False): """ Given a ticket string and service identifier, validate the corresponding ``Ticket``. If validation succeeds, return the ``Ticket``. If validation fails, raise an appropriate error. If ``renew`` is ``True``, ``ServiceTicket`` validation will only succeed if the ticket was issued from the presentation of the user's primary credentials. If ``require_https`` is ``True``, ``ServiceTicket`` validation will only succeed if the service URL scheme is HTTPS. """ if not ticket: raise InvalidRequest("No ticket string provided") if not self.model.TICKET_RE.match(ticket): raise InvalidTicket("Ticket string %s is invalid" % ticket) try: t = self.get(ticket=ticket) except self.model.DoesNotExist: raise InvalidTicket("Ticket %s does not exist" % ticket) if t.is_consumed(): raise InvalidTicket("%s %s has already been used" % (t.name, ticket)) if t.is_expired(): raise InvalidTicket("%s %s has expired" % (t.name, ticket)) if not service: raise InvalidRequest("No service identifier provided") if require_https and not is_scheme_https(service): raise InvalidService("Service %s is not HTTPS" % service) if not is_valid_service_url(service): raise InvalidService("Service %s is not a valid %s URL" % (service, t.name)) try: if not same_origin(t.service, service): raise InvalidService("%s %s for service %s is invalid for " "service %s" % (t.name, ticket, t.service, service)) except AttributeError: pass try: if renew and not t.is_primary(): raise InvalidTicket("%s %s was not issued via primary " "credentials" % (t.name, ticket)) except AttributeError: pass logger.debug("Validated %s %s" % (t.name, ticket)) return t
def validate_service_ticket(self, service, ticket, pgturl, renew): """ Validate a service ticket string. Return a triplet containing a ``ServiceTicket`` and an optional ``ProxyGrantingTicket``, or a ``ValidationError`` subclass if ticket validation failed. """ logger.debug("Service validation request received for %s" % ticket) # Check for proxy tickets passed to /serviceValidate if ticket and ticket.startswith(ProxyTicket.TICKET_PREFIX): e = InvalidTicket('Proxy tickets cannot be validated' ' with /serviceValidate') logger.warning("%s %s" % (e.code, e)) return None, None, e try: st = ServiceTicket.objects.validate_ticket(ticket, service, renew=renew) except ValidationError as e: logger.warning("%s %s" % (e.code, e)) return None, None, e else: if pgturl: logger.debug("Proxy-granting ticket request received for %s" % pgturl) pgt = ProxyGrantingTicket.objects.create_ticket( pgturl, user=st.user, granted_by_st=st) else: pgt = None return st, pgt, None
def test_validation_response_error(self): """ When given an error, a ``ValidationResponse`` should return an authentication failure with the error code and text. """ error = InvalidTicket('Testing Error') resp = ValidationResponse(context={'ticket': None, 'error': error}, content_type='text/xml') failure = parse(resp.content).find('./authenticationFailure') self.assertIsNotNone(failure) self.assertEqual(failure.get('code'), 'INVALID_TICKET') self.assertEqual(failure.text, 'Testing Error')
def test_saml_validation_response_error(self): """ When given an error, a ``SamlValidationResponse`` should return an authentication failure with the error text. """ error = InvalidTicket('Testing Error') resp = SamlValidationResponse(context={'ticket': None, 'error': error}, content_type='text/xml') code = parse(resp.content).find('./Body/Response/Status/StatusCode') self.assertIsNotNone(code) self.assertEqual(code.get('Value'), 'samlp:RequestDenied') message = parse(resp.content).find('./Body/Response/Status/StatusMessage') self.assertIsNotNone(message) self.assertEqual(message.text, 'Testing Error')