1: <?php
2: /**
3: *
4: */
5: abstract class RESTian_Auth_Provider_Base {
6:
7: /**
8: * @var RESTian_Client
9: */
10: var $api;
11:
12: /**
13: * @var string RESTian-specific authorization type identifier, like 'basic_http', etc.
14: */
15: var $auth_type;
16:
17: /**
18: * @var string To contain something like '1.0a', to be set by subclass if needed.
19: */
20: var $auth_version;
21:
22: /**
23: * @var string Allows auth provider to set a user readable message
24: */
25: var $message;
26:
27: /**
28: * @param RESTian_Client $api
29: */
30: function __construct( $api ) {
31: $this->api = $api;
32: }
33:
34: /**
35: * Allow auth provider to process credentials
36: *
37: * @param array $credentials
38: * @return array
39: */
40: function prepare_credentials( $credentials ) {
41: return $credentials;
42: }
43:
44: /**
45: * Allow auth provider to process grant
46: *
47: * @param array $grant
48: * @param array $credentials
49: * @return array
50: */
51: function prepare_grant( $grant, $credentials ) {
52: return $grant;
53: }
54:
55: /**
56: * @return array
57: */
58: function get_new_credentials() {
59: return array();
60: }
61:
62: /**
63: * @return array
64: */
65: function get_new_grant() {
66: return array();
67: }
68:
69: /**
70: * Determine if provided credentials represent a viable set of credentials
71: *
72: * Default behavior ensures that all credential elements exist, i.e. if username and password are required
73: * this code ensures both username and password have a value. Subclasses can add or relax requirements using
74: * their own algorithms as required.
75: *
76: * @param array $credentials
77: * @return bool
78: */
79: function is_credentials( $credentials ) {
80: $is_credentials = true;
81: if ( ! $this->_has_required( $this->get_new_credentials(), $credentials ) ) {
82: $is_credentials = false;
83: $this->message = 'The required credentials were not provided.';
84: }
85: return $is_credentials;
86: }
87:
88: /**
89: * Determine if provided grant represents a viable grant
90: *
91: * Default behavior ensures that all grant elements exist, i.e. if access_token and refresh_token are required
92: * this code ensures both access_token and refresh_token have a value. Subclasses can add or relax requirements
93: * using their own algorithms as required.
94: *
95: * @param array $grant
96: * @return bool
97: */
98: function is_grant( $grant ) {
99: return $this->_has_required( $this->get_new_grant(), $grant );
100: }
101:
102: /**
103: * Extract grant from the passed $auth_settings.
104: *
105: * @param array $auth_settings
106: * @return array
107: */
108: function extract_grant( $auth_settings ) {
109: return array_intersect_key( $auth_settings, $this->get_new_grant() );
110: }
111:
112: /**
113: * Extract credentials from the passed $auth_settings.
114: *
115: * @param array $auth_settings
116: * @return array
117: */
118: function extract_credentials( $auth_settings ) {
119: return array_intersect_key( $auth_settings, $this->get_new_credentials() );
120: }
121:
122:
123: /**
124: * Test to see if the request has prerequisites required to authenticate, i.e. credentials.
125: *
126: * Defaults to making sure that the request has valid credentials; subclasses can modify as required.
127: *
128: * @param array $credentials
129: * @return bool
130: */
131: function has_prerequisites( $credentials ) {
132: return $this->is_credentials( $credentials );
133: }
134:
135: /**
136: * Allows an auth provider to decorate a RESTian_Request prior to $request->make_request(), as required.
137: *
138: * @param RESTian_Request $request
139: */
140: function prepare_request( $request ) {
141: }
142:
143: /**
144: * Allows an auth provider to handle a response; returns true if handled, false otherwise.
145: *
146: * The auth provider does not have to handle every response.
147: *
148: * @param RESTian_Response $response
149: * @return bool
150: */
151: function handle_response( $response ) {
152: return false;
153: }
154:
155: /**
156: * Takes the response and capture the grant in the format $this->is_grant() will validate
157: *
158: * @param RESTian_Response $response
159: */
160: function capture_grant( $response ) {
161: $response->grant = array( 'authenticated' => $response->authenticated );
162: }
163:
164: /**
165: * Tests a RESTian_Response returning true if the response was authenticated, false otherwise.
166: *
167: * Default is an HTTP 200 or 204 status code; subclasses can modify as required.
168: *
169: * @see: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success
170: *
171: * @param RESTian_Response $response
172: * @return bool
173: */
174: function authenticated( $response ) {
175: return preg_match( '#^(200|204)$#', $response->status_code );
176: }
177:
178: /**
179: * Return an error message
180: *
181: * @param string $code
182: * @return string
183: */
184: function get_error_message( $code ) {
185: switch ( $code ) {
186: case 'NO_AUTH':
187: $message = 'Either the username and/or password were not provided. This is likely a programmer error. Please contact the site\'s owner.';
188: break;
189:
190: case 'BAD_AUTH':
191: $message = "Your username and password combination were not recognized by the {$this->api->api_name}.";
192: break;
193:
194: default:
195: $message = false;
196: break;
197: }
198: return $message;
199: }
200:
201: /**
202: * Tests an array to ensure it has all required elements given a pattern array.
203: *
204: * @examples:
205: *
206: * $pattern = array( 'a' => '', 'b' => '', 'c' => '' );
207: * $array = array( 'a' => 'foo', 'b' => 'bar', 'd' => 'baz' );
208: * $this->_has_required( $pattern, $array ) // returns false because !isset($array['c'])
209: *
210: * $pattern = array( 'a' => '', 'b' => '', 'c' => '' );
211: * $array = array( 'a' => 'foo', 'b' => 'bar', 'c' => 'baz', 'd' => 'bezong' );
212: * $this->_has_required( $pattern, $array ) // returns true because !isset($array['d']) is irrelevant.
213: *
214: * @param array $pattern_array
215: * @param array $array_to_test
216: *
217: * @return bool
218: */
219: protected function _has_required( $pattern_array, $array_to_test ) {
220: $has_required = true;
221: foreach( array_keys( $pattern_array ) as $key ) {
222: if ( empty( $array_to_test[$key] ) ) {
223: $has_required = false;
224: break;
225: }
226: }
227: return $has_required;
228: }
229: }
230: