1+ <?php
2+ /**
3+ * Strong Authentication
4+ *
5+ * Use this middleware with your Slim Framework application
6+ * to require HTTP basic auth for all routes.
7+ *
8+ * @author Andrew Smith <[email protected] > 9+ * @version 1.0
10+ * @copyright 2012 Andrew Smith
11+ *
12+ * USAGE
13+ *
14+ * $app = new Slim();
15+ * $app->add(new StrongAuth(array('provider' => 'PDO', 'dsn' => 'sqlite:memory')));
16+ *
17+ * MIT LICENSE
18+ *
19+ * Permission is hereby granted, free of charge, to any person obtaining
20+ * a copy of this software and associated documentation files (the
21+ * "Software"), to deal in the Software without restriction, including
22+ * without limitation the rights to use, copy, modify, merge, publish,
23+ * distribute, sublicense, and/or sell copies of the Software, and to
24+ * permit persons to whom the Software is furnished to do so, subject to
25+ * the following conditions:
26+ *
27+ * The above copyright notice and this permission notice shall be
28+ * included in all copies or substantial portions of the Software.
29+ *
30+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
34+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
35+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37+ */
38+ class StrongAuth extends Slim_Middleware {
39+ /**
40+ * @var string
41+ */
42+ protected $ realm ;
43+
44+ /**
45+ * @var string
46+ */
47+ protected $ username ;
48+
49+ /**
50+ * @var string
51+ */
52+ protected $ password ;
53+
54+ /**
55+ * @var array
56+ */
57+ protected $ settings = array (
58+ 'login.url ' => '/ ' ,
59+ 'auth_type ' => 'http ' ,
60+ );
61+
62+ /**
63+ * Constructor
64+ *
65+ * @param array $config Configuration for Strong and Login Details
66+ * @return void
67+ */
68+ public function __construct (array $ config = array ()) {
69+ $ this ->config = array_merge ($ this ->settings , $ config );
70+ }
71+
72+ /**
73+ * Call
74+ *
75+ * @return void
76+ */
77+ public function call () {
78+ $ app = $ this ->app ;
79+ $ config = $ this ->config ;
80+
81+ $ req = $ this ->app ->request ();
82+
83+ // Authentication Initialised
84+ $ auth = Strong::factory ($ this ->config );
85+ switch ($ this ->config ['auth_type ' ]) {
86+ case 'form ' :
87+ $ this ->formauth ($ auth , $ req );
88+ break ;
89+ default :
90+ $ this ->httpauth ($ auth , $ req );
91+ break ;
92+ }
93+ }
94+
95+ /**
96+ * Form based authentication
97+ *
98+ * @param Strong $auth
99+ * @param object $req
100+ */
101+ private function formauth (Strong $ auth , $ req ) {
102+ $ app = $ this ->app ;
103+ $ config = $ this ->config ;
104+
105+ $ this ->app ->hook ('slim.before.router ' , function () use ($ app , $ auth , $ req , $ config ) {
106+ $ secured_urls = isset ($ config ['security.urls ' ]) ? $ config ['security.urls ' ] : array ();
107+ foreach ($ secured_urls as $ surl ) {
108+ $ patternAsRegex = $ surl ['path ' ];
109+ if (substr ($ surl ['path ' ], -1 ) === '/ ' ) {
110+ $ patternAsRegex = $ patternAsRegex . '? ' ;
111+ }
112+ $ patternAsRegex = '@^ ' . $ patternAsRegex . '$@ ' ;
113+
114+ if (preg_match ($ patternAsRegex , $ req ->getPathInfo ())) {
115+ if (!$ auth ->loggedIn ()) {
116+ if ($ req ->getPath () !== $ config ['login.url ' ]) {
117+ $ app ->redirect ($ config ['login.url ' ]);
118+ }
119+ }
120+ }
121+ }
122+ });
123+
124+ $ this ->next ->call ();
125+ }
126+
127+ /**
128+ * HTTPAuth based authentication
129+ *
130+ * This method will check the HTTP request headers for previous authentication. If
131+ * the request has already authenticated, the next middleware is called. Otherwise,
132+ * a 401 Authentication Required response is returned to the client.
133+ *
134+ * @param Strong $auth
135+ * @param object $req
136+ */
137+ private function httpauth (Strong $ auth , $ req ) {
138+ $ res = $ this ->app ->response ();
139+ $ authUser = $ req ->headers ('PHP_AUTH_USER ' );
140+ $ authPass = $ req ->headers ('PHP_AUTH_PW ' );
141+
142+ if ( $ authUser && $ authPass && $ auth ->login ($ authUser , $ authPass ) ) {
143+ $ this ->next ->call ();
144+ } else {
145+ $ res ->status (401 );
146+ $ res ->header ('WWW-Authenticate ' , sprintf ('Basic realm="%s" ' , $ this ->realm ));
147+ }
148+ }
149+ }
0 commit comments