ValidateController::validateRequest()   B
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 31
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 31
rs 8.5806
cc 4
eloc 15
nc 4
nop 2
1
<?php
2
/**
3
 * Validate controller class.
4
 *
5
 * @version 1.2.0
6
 * @since 1.2.0
7
 */
8
9
namespace Cassava\CAS\Controller;
10
11
use Cassava\CAS;
12
use Cassava\Exception\GeneralException;
13
use Cassava\Exception\RequestException;
14
use Cassava\Exception\TicketException;
15
16
/**
17
 * Implements CAS 1.0 ticket validation.
18
 *
19
 * `/validate` is a CAS 1.0 protocol method that checks the validity of a service ticket.
20
 *
21
 * Being part of the CAS 1.0 protocol, `/validate` does not handle proxy authentication.
22
 *
23
 * The following HTTP request parameters may be specified:
24
 *
25
 * - `service` (required): The URL of the service for which the ticket was issued.
26
 * - `ticket` (required): The service ticket issued by `/login`.
27
 * - `renew` (optional): If this parameter is set, the server will force the user to reenter
28
 *   their primary credentials.
29
 *
30
 * `/validate` will return one of the following two responses:
31
 *
32
 * On successful validation:
33
 *
34
 * ```
35
 * yes\n
36
 * username\n
37
 * ```
38
 *
39
 * On validation failure:
40
 *
41
 * ```
42
 * no\n
43
 * \n
44
 * ```
45
 *
46
 * @since 1.2.0
47
 */
48
class ValidateController extends BaseController {
49
50
	/**
51
	 * Valid ticket types.
52
	 *
53
	 * `/validate` checks the validity of a service ticket. `/validate` is part of the CAS 1.0
54
	 * protocol and thus does not handle proxy authentication. CAS MUST respond with a ticket
55
	 * validation failure response when a proxy ticket is passed to `/validate`.
56
	 *
57
	 * @var array
58
	 */
59
	protected $validTicketTypes = array(
60
		CAS\Ticket::TYPE_ST,
61
	);
62
63
	/**
64
	 * Handles ticket validation requests.
65
	 *
66
	 * This method will attempt to set a `Content-Type: text/plain` HTTP header when called.
67
	 *
68
	 * @param  array  $request Request arguments.
69
	 * @return string          Validation response.
70
	 */
71
	public function handleRequest( $request ) {
72
		$this->server->setResponseContentType( 'text/plain' );
73
74
		$service = isset( $request['service'] ) ? $request['service'] : '';
75
		$ticket  = isset( $request['ticket'] )  ? $request['ticket']  : '';
76
77
		try {
78
			$ticket = $this->validateRequest( $ticket, $service );
79
		}
80
		catch ( GeneralException $exception ) {
81
			return "no\n\n";
82
		}
83
84
		return "yes\n" . $ticket->user->user_login . "\n";
85
	}
86
87
	/**
88
	 * Validates a ticket, returning a ticket object, or throws an exception.
89
	 *
90
	 * Triggers the `cas_server_validation_success` action on ticket validation.
91
	 *
92
	 * @param  string      $ticket  Service or proxy ticket.
93
	 * @param  string      $service Service URI.
94
	 * @return CAS\Ticket          Valid ticket object associated with request.
95
	 *
96
	 * @uses \do_action()
97
	 * @uses \esc_url_raw()
98
	 *
99
	 * @throws \Cassava\Exception\RequestException
100
	 * @throws \Cassava\Exception\TicketException
101
	 */
102
	protected function validateRequest( $ticket = '', $service = '' ) {
103
104
		if ( empty( $ticket ) ) {
105
			throw new RequestException( __( 'Ticket is required.', 'wp-cas-server' ) );
106
		}
107
108
		if ( empty( $service ) ) {
109
			throw new RequestException( __( 'Service is required.', 'wp-cas-server' ) );
110
		}
111
112
		$service = esc_url_raw( $service );
113
114
		CAS\Ticket::validateAllowedTypes( $ticket, $this->validTicketTypes );
115
		$ticket = CAS\Ticket::fromString( $ticket );
116
		$ticket->markUsed();
117
118
		if ( $ticket->service !== $service ) {
119
			throw new RequestException(
120
				__( 'Ticket does not match the service provided.', 'wp-cas-server' ),
121
				RequestException::ERROR_INVALID_SERVICE );
122
		}
123
124
		/**
125
		 * Fires on successful ticket validation.
126
		 *
127
		 * @param \Cassava\CAS\Ticket $ticket Valid ticket object.
128
		 */
129
		\do_action( 'cas_server_validation_success', $ticket );
130
131
		return $ticket;
132
	}
133
134
}
135