Completed
Push — master ( 694417...116d3c )
by Dominik
04:44
created

HybridEndPointController::getAzineHybridAuth()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Azine\HybridAuthBundle\Controller;
4
5
use Symfony\Component\HttpFoundation\ParameterBag;
6
7
use Symfony\Component\HttpFoundation\RedirectResponse;
8
9
use Symfony\Component\HttpFoundation\Response;
10
11
use Symfony\Component\HttpFoundation\Request;
12
13
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
14
15
class HybridEndPointController extends Controller {
16
17
	private $initDone = FALSE;
18
	/**
19
	 * @var \Hybrid_Auth
20
	 */
21
	private $hybridAuth;
22
23
	/**
24
	 * @var ParameterBag
25
	 */
26
	private $requestQuery;
27
28
    /**
29
     * Process the current request
30
     *
31
     * $request - The current request parameters. Leave as NULL to default to use $_REQUEST.
32
     * @param Request $request
33
     * @return RedirectResponse|Response
34
     */
35
	public function processAction(Request $request) {
36
		// Get the request Vars
37
		$this->requestQuery = $request->query;
38
39
		// init the hybridAuth instance
40
		$provider = trim( strip_tags( $this->requestQuery->get("hauth_start") ) );
41
		$cookieName = $this->get("azine_hybrid_auth_service")->getCookieName($provider);
42
		$this->hybridAuth =  $this->get("azine_hybrid_auth_service")->getInstance($request->cookies->get($cookieName), $provider);
43
44
		// If openid_policy requested, we return our policy document
45
		if ( $this->requestQuery->has('get') && $this->requestQuery->get('get') == "openid_policy" ) {
46
			return $this->processOpenidPolicy();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->processOpenidPolicy(); (string) is incompatible with the return type documented by Azine\HybridAuthBundle\C...ntroller::processAction of type Symfony\Component\HttpFoundation\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
47
		}
48
49
		// If openid_xrds requested, we return our XRDS document
50
		if ( $this->requestQuery->has('get') && $this->requestQuery->get('get') == "openid_xrds" ) {
51
			return $this->processOpenidXRDS();
52
		}
53
54
		// If we get a hauth.start
55
		if ( $this->requestQuery->has('hauth_start') && $this->requestQuery->get('hauth_start') ) {
56
			return $this->processAuthStart();
57
		}
58
		// Else if hauth.done
59
		elseif ( $this->requestQuery->has('hauth_done') && $this->requestQuery->get('hauth_done') ) {
60
			return $this->processAuthDone($request);
61
		}
62
		// Else we advertise our XRDS document, something supposed to be done from the Realm URL page
63
		else {
64
			return $this->processOpenidRealm();
65
		}
66
	}
67
68
	/**
69
	 * Process OpenID policy request
70
	 */
71
	private function processOpenidPolicy() {
72
		$output = file_get_contents( dirname(__FILE__) . "/resources/openid_policy.html" );
73
		return $output;
74
	}
75
76
	/**
77
	 * Process OpenID XRDS request
78
	 */
79
	private function processOpenidXRDS() {
80
		header("Content-Type: application/xrds+xml");
81
82
		$output = str_replace
83
		(
84
				"{RETURN_TO_URL}",
85
				str_replace(
86
						array("<", ">", "\"", "'", "&"), array("&lt;", "&gt;", "&quot;", "&apos;", "&amp;"),
87
						$this->hybridAuth->getCurrentUrl( false )
88
				),
89
				file_get_contents( dirname(__FILE__) . "/resources/openid_xrds.xml" )
90
		);
91
		return new Response($output);
92
	}
93
94
	/**
95
	 * Process OpenID realm request
96
	 */
97
	private function processOpenidRealm()	{
98
99
		$output = str_replace
100
		(
101
				"{X_XRDS_LOCATION}",
102
				htmlentities( $this->hybridAuth->getCurrentUrl( false ), ENT_QUOTES, 'UTF-8' ) . "?get=openid_xrds&v=" . \Hybrid_Auth::$version,
103
				file_get_contents( dirname(__FILE__) . "/resources/openid_realm.html" )
104
		);
105
		return new Response($output);
106
	}
107
108
	/**
109
	 * define:endpoint step 3.
110
	 */
111
	private function processAuthStart() {
112
113
		$response = $this->authInit();
114
		if($response instanceof Response){
115
			return $response;
116
		}
117
118
		$provider_id = trim( strip_tags( $this->requestQuery->get("hauth_start") ) );
119
120
		# check if page accessed directly
121
		if( ! $this->hybridAuth->storage()->get( "hauth_session.$provider_id.hauth_endpoint" ) ) {
122
			\Hybrid_Logger::error( "Endpoint: hauth_endpoint parameter is not defined on hauth_start, halt login process!" );
123
124
			return new Response("You cannot access this page directly.", 404, array(header( "HTTP/1.0 404 Not Found" )));
125
		}
126
127
		# define:hybrid.endpoint.php step 2.
128
		$hauth = $this->hybridAuth->setup( $provider_id );
129
130
		# if REQUESTed hauth_idprovider is wrong, session not created, etc.
131
		if( ! $hauth ) {
132
			\Hybrid_Logger::error( "Endpoint: Invalid parameter on hauth_start!" );
133
134
			return new Response("Invalid parameter! Please return to the login page and try again.", 404, array(header( "HTTP/1.0 404 Not Found" )));
135
		}
136
137
		try {
138
			\Hybrid_Logger::info( "Endpoint: call adapter [{$provider_id}] loginBegin()" );
139
140
			$hauth->adapter->loginBegin();
141
		}
142
		catch ( \Exception $e ) {
143
			$logger = $this->get("logger");
144
			$logger->error("Exception:  Code: " . $e->getCode() . "; Message: " . $e->getMessage(), $e->getTrace());
145
			if($e->getPrevious() != null && $e->getPrevious() != $e){
146
				$p = $e->getPrevious();
147
				$logger->error("Exception:  Code: " . $p->getCode() . "; Message: " . $p->getMessage(), $p->getTrace());
148
			}
149
			// replace the callback_url with the referrer.
150
			if(isset($_SERVER['HTTP_REFERER'])){
151
				$this->hybridAuth->storage()->set( "hauth_session.$provider_id.hauth_return_to", $_SERVER['HTTP_REFERER'] );
152
			} else {
153
				// or go back in the browser-history via js
154
				return new Response("<html><body onload='window.history.back();'><h1>An Error occured.</h1>Going back one step in the browser history.</body></html>", 500);				
155
			}
156
		}
157
		return $this->returnToCallbackUrl($provider_id);
158
	}
159
160
	/**
161
	 * define:endpoint step 3.1 and 3.2
162
	 */
163
	private function processAuthDone(Request $request) {
164
165
		$this->authInit();
166
167
		$provider_id = trim( strip_tags( $this->requestQuery->get("hauth_done") ) );
168
169
		$hauth = $this->hybridAuth->setup( $provider_id );
170
171
		$authCookie = null;
172
173
		if( ! $hauth ) {
174
			\Hybrid_Logger::error( "Endpoint: Invalid parameter on hauth_done!" );
175
176
			$hauth->adapter->setUserUnconnected();
177
178
			return new Response("Invalid parameter! Please return to the login page and try again.", 404, array(header( "HTTP/1.0 404 Not Found" )));
179
		}
180
181
		try {
182
			\Hybrid_Logger::info( "Endpoint: call adapter [{$provider_id}] loginFinish() " );
183
184
			$hauth->adapter->loginFinish();
185
186
			// store auth-session-data
187
			$authCookie = $this->get("azine_hybrid_auth_service")->storeHybridAuthSessionData($request, $provider_id, $this->hybridAuth->getSessionData());
188
		}
189
		catch( \Exception $e ){
190
			\Hybrid_Logger::error( "Exception:" . $e->getMessage()."\n\n".$e->getTraceAsString() );
191
			\Hybrid_Error::setError( $e->getMessage(), $e->getCode(), $e->getTraceAsString(), $e->getPrevious());
192
193
			$hauth->adapter->setUserUnconnected();
194
			
195
		}
196
197
		\Hybrid_Logger::info( "Endpoint: job done. retrun to callback url." );
198
199
		$response = $this->returnToCallbackUrl($provider_id);
200
201
		// add auth-session-data into cookie
202
		if($authCookie){
203
			$response->headers->setCookie($authCookie);
204
		}
205
		return $response;
206
	}
207
208
	private function authInit() {
209
210
		if ( ! $this->initDone) {
211
			$this->initDone = TRUE;
212
213
			# Init Hybrid_Auth
214
			try {
215
				if(!class_exists("Hybrid_Storage")){
216
					require_once realpath( dirname( __FILE__ ) )  . "/Storage.php";
217
				}
218
219
				$storage = new \Hybrid_Storage();
220
221
				// Check if Hybrid_Auth session already exist
222
				if ( ! $storage->config( "CONFIG" ) ) {
223
					return new Response("You cannot access this page directly.", 500, array(header( "HTTP/1.0 500 Server Error" )));
224
				}
225
226
				$this->hybridAuth->initialize( $storage->config( "CONFIG" ) );
227
			}
228
			catch ( \Exception $e ){
229
				\Hybrid_Logger::error( "Endpoint: Error while trying to init Hybrid_Auth" );
230
231
				return new Response("Oophs. Error!", 500, array(header( "HTTP/1.0 500 Server Error" )));
232
			}
233
		}
234
	}
235
236
	private function returnToCallbackUrl($provider_id) {
237
		// get the stored callback url
238
		$callback_url = $this->hybridAuth->storage()->get( "hauth_session.$provider_id.hauth_return_to" );
239
240
		// remove some unneeded stored data
241
		$this->hybridAuth->storage()->delete( "hauth_session.$provider_id.hauth_return_to"    );
242
		$this->hybridAuth->storage()->delete( "hauth_session.$provider_id.hauth_endpoint"     );
243
		$this->hybridAuth->storage()->delete( "hauth_session.$provider_id.id_provider_params" );
244
245
		// back to home
246
		return new RedirectResponse($callback_url);
247
	}
248
249
}
250