Skip to content
This repository was archived by the owner on Jul 24, 2023. It is now read-only.

Commit 846c128

Browse files
committed
Working on windows authentication middleware
1 parent 4b16a74 commit 846c128

File tree

3 files changed

+354
-247
lines changed

3 files changed

+354
-247
lines changed

src/AdldapAuthUserProvider.php

Lines changed: 3 additions & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
namespace Adldap\Laravel;
44

55
use Adldap\Laravel\Facades\Adldap;
6+
use Adldap\Laravel\Traits\ImportsUsers;
67
use Adldap\Models\User;
78
use Adldap\Schemas\ActiveDirectory;
89
use Illuminate\Auth\EloquentUserProvider;
910
use Illuminate\Contracts\Auth\Authenticatable;
10-
use Illuminate\Database\Eloquent\Model;
1111
use Illuminate\Support\Arr;
1212
use Illuminate\Support\Facades\Config;
1313

1414
class AdldapAuthUserProvider extends EloquentUserProvider
1515
{
16+
use ImportsUsers;
17+
1618
/**
1719
* {@inheritdoc}
1820
*/
@@ -84,111 +86,6 @@ public function retrieveByCredentials(array $credentials)
8486
return;
8587
}
8688

87-
/**
88-
* Creates a local User from Active Directory.
89-
*
90-
* @param User $user
91-
* @param string $password
92-
*
93-
* @return \Illuminate\Database\Eloquent\Model
94-
*/
95-
protected function getModelFromAdldap(User $user, $password)
96-
{
97-
// Get the username attributes.
98-
$attributes = $this->getUsernameAttribute();
99-
100-
// Get the model key.
101-
$key = key($attributes);
102-
103-
// Get the username from the AD model.
104-
$username = $user->{$attributes[$key]};
105-
106-
// Make sure we retrieve the first username
107-
// result if it's an array.
108-
if (is_array($username)) {
109-
$username = Arr::get($username, 0);
110-
}
111-
112-
// Try to retrieve the model from the model key and AD username.
113-
$model = $this->createModel()->newQuery()->where([$key => $username])->first();
114-
115-
// Create the model instance of it isn't found.
116-
if (!$model instanceof Model) {
117-
$model = $this->createModel();
118-
}
119-
120-
// Set the username and password in case
121-
// of changes in active directory.
122-
$model->{$key} = $username;
123-
124-
// Sync the users password.
125-
$model = $this->syncModelPassword($model, $password);
126-
127-
// Synchronize other active directory
128-
// attributes on the model.
129-
$model = $this->syncModelFromAdldap($user, $model);
130-
131-
if ($this->getBindUserToModel()) {
132-
$model = $this->bindAdldapToModel($user, $model);
133-
}
134-
135-
return $model;
136-
}
137-
138-
/**
139-
* Fills a models attributes by the specified Users attributes.
140-
*
141-
* @param User $user
142-
* @param Authenticatable $model
143-
*
144-
* @return Authenticatable
145-
*/
146-
protected function syncModelFromAdldap(User $user, Authenticatable $model)
147-
{
148-
$attributes = $this->getSyncAttributes();
149-
150-
foreach ($attributes as $modelField => $adField) {
151-
if ($this->isAttributeCallback($adField)) {
152-
$value = $this->handleAttributeCallback($user, $adField);
153-
} else {
154-
$value = $this->handleAttributeRetrieval($user, $adField);
155-
}
156-
157-
$model->{$modelField} = $value;
158-
}
159-
160-
if ($model instanceof Model) {
161-
$model->save();
162-
}
163-
164-
return $model;
165-
}
166-
167-
/**
168-
* Syncs the models password with the specified password.
169-
*
170-
* @param Authenticatable $model
171-
* @param string $password
172-
*
173-
* @return Authenticatable
174-
*/
175-
protected function syncModelPassword(Authenticatable $model, $password)
176-
{
177-
if ($model instanceof Model && $model->hasSetMutator('password')) {
178-
// If the model has a set mutator for the password then
179-
// we'll assume that the dev is using their
180-
// own encryption method for passwords.
181-
$model->password = $password;
182-
183-
return $model;
184-
}
185-
186-
// Always encrypt the model password by default.
187-
$model->password = bcrypt($password);
188-
189-
return $model;
190-
}
191-
19289
/**
19390
* Retrieves the Adldap User model from the
19491
* specified Laravel model.
@@ -218,32 +115,6 @@ protected function discoverAdldapFromModel($model)
218115
return $model;
219116
}
220117

221-
/**
222-
* Binds the Adldap User instance to the Eloquent model instance
223-
* by setting its `adldapUser` public property.
224-
*
225-
* @param User $user
226-
* @param Authenticatable $model
227-
*
228-
* @return Authenticatable
229-
*/
230-
protected function bindAdldapToModel(User $user, Authenticatable $model)
231-
{
232-
$model->adldapUser = $user;
233-
234-
return $model;
235-
}
236-
237-
/**
238-
* Returns a new Adldap user query.
239-
*
240-
* @return \Adldap\Query\Builder
241-
*/
242-
protected function newAdldapUserQuery()
243-
{
244-
return Adldap::users()->search()->select($this->getSelectAttributes());
245-
}
246-
247118
/**
248119
* Authenticates a user against Active Directory.
249120
*
@@ -257,78 +128,6 @@ protected function authenticate($username, $password)
257128
return Adldap::authenticate($username, $password);
258129
}
259130

260-
/**
261-
* Returns true / false if the specified string
262-
* is a callback for an attribute handler.
263-
*
264-
* @param string $string
265-
*
266-
* @return bool
267-
*/
268-
protected function isAttributeCallback($string)
269-
{
270-
$matches = preg_grep("/(\w)@(\w)/", explode("\n", $string));
271-
272-
return count($matches) > 0;
273-
}
274-
275-
/**
276-
* Handles retrieving the value from an attribute callback.
277-
*
278-
* @param User $user
279-
* @param string $callback
280-
*
281-
* @return mixed
282-
*/
283-
protected function handleAttributeCallback(User $user, $callback)
284-
{
285-
// Explode the callback into its class and method.
286-
list($class, $method) = explode('@', $callback);
287-
288-
// Create the handler.
289-
$handler = app($class);
290-
291-
// Call the attribute handler method and return the result.
292-
return call_user_func_array([$handler, $method], [$user]);
293-
}
294-
295-
/**
296-
* Handles retrieving the specified field from the User model.
297-
*
298-
* @param User $user
299-
* @param string $field
300-
*
301-
* @return string|null
302-
*/
303-
protected function handleAttributeRetrieval(User $user, $field)
304-
{
305-
if ($field === ActiveDirectory::THUMBNAIL) {
306-
// If the field we're retrieving is the users thumbnail photo, we need
307-
// to retrieve it encoded so we're able to save it to the database.
308-
$value = $user->getThumbnailEncoded();
309-
} else {
310-
$value = $user->{$field};
311-
312-
if (is_array($value)) {
313-
// If the AD Value is an array, we'll
314-
// retrieve the first value.
315-
$value = Arr::get($value, 0);
316-
}
317-
}
318-
319-
return $value;
320-
}
321-
322-
/**
323-
* Returns the username attribute for discovering LDAP users.
324-
*
325-
* @return array
326-
*/
327-
protected function getUsernameAttribute()
328-
{
329-
return Config::get('adldap_auth.username_attribute', ['username' => ActiveDirectory::ACCOUNT_NAME]);
330-
}
331-
332131
/**
333132
* Returns the password key to retrieve the
334133
* password from the user input array.
@@ -340,49 +139,6 @@ protected function getPasswordKey()
340139
return Config::get('adldap_auth.password_key', 'password');
341140
}
342141

343-
/**
344-
* Retrieves the Adldap login attribute for authenticating users.
345-
*
346-
* @return string
347-
*/
348-
protected function getLoginAttribute()
349-
{
350-
return Config::get('adldap_auth.login_attribute', ActiveDirectory::ACCOUNT_NAME);
351-
}
352-
353-
/**
354-
* Retrieves the Adldap bind user to model config option for binding
355-
* the Adldap user model instance to the laravel model.
356-
*
357-
* @return bool
358-
*/
359-
protected function getBindUserToModel()
360-
{
361-
return Config::get('adldap_auth.bind_user_to_model', false);
362-
}
363-
364-
/**
365-
* Retrieves the Adldap sync attributes for filling the
366-
* Laravel user model with active directory fields.
367-
*
368-
* @return array
369-
*/
370-
protected function getSyncAttributes()
371-
{
372-
return Config::get('adldap_auth.sync_attributes', ['name' => ActiveDirectory::COMMON_NAME]);
373-
}
374-
375-
/**
376-
* Retrieves the Aldldap select attributes when performing
377-
* queries for authentication and binding for users.
378-
*
379-
* @return array
380-
*/
381-
protected function getSelectAttributes()
382-
{
383-
return Config::get('adldap_auth.select_attributes', []);
384-
}
385-
386142
/**
387143
* Retrieves the Adldap login fallback option for falling back
388144
* to the local database if AD authentication fails.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
namespace Adldap\Laravel\Middleware;
4+
5+
use Closure;
6+
use Adldap\Models\User;
7+
use Adldap\Laravel\Traits\ImportsUsers;
8+
use Illuminate\Contracts\Auth\Guard;
9+
use Illuminate\Database\Eloquent\Model;
10+
use Illuminate\Http\Request;
11+
12+
class WindowsAuthenticate
13+
{
14+
use ImportsUsers;
15+
16+
/**
17+
* The authenticator implementation.
18+
*
19+
* @var \Illuminate\Contracts\Auth\Guard
20+
*/
21+
protected $auth;
22+
23+
/**
24+
* Create a new filter instance.
25+
*
26+
* @param Guard $auth
27+
*/
28+
public function __construct(Guard $auth)
29+
{
30+
$this->auth = $auth;
31+
}
32+
33+
/**
34+
* Handle an incoming request.
35+
*
36+
* @param Request $request
37+
* @param Closure $next
38+
*
39+
* @return mixed
40+
*/
41+
public function handle(Request $request, Closure $next)
42+
{
43+
// Handle Windows Authentication.
44+
if ($account = $request->server('AUTH_USER')) {
45+
// Usernames will be prefixed with their domain,
46+
// we just need their account name.
47+
list($domain, $username) = explode('\\', $account);
48+
49+
// Create a new user LDAP user query.
50+
$query = $this->newAdldapUserQuery();
51+
52+
// Get the username input attributes
53+
$attributes = $this->getUsernameAttribute();
54+
55+
// Get the input key
56+
$key = key($attributes);
57+
58+
// Filter the query by the username attribute
59+
$query->whereEquals($attributes[$key], $username);
60+
61+
// Retrieve the first user result
62+
$user = $query->first();
63+
64+
if ($user instanceof User) {
65+
$model = $this->getModelFromAdldap($user, str_random());
66+
67+
if ($model instanceof Model && $this->auth->guest()) {
68+
// Double check user instance before logging them in.
69+
$this->auth->login($user);
70+
}
71+
}
72+
}
73+
74+
return $next($request);
75+
}
76+
77+
/**
78+
* Returns a new auth model instance.
79+
*
80+
* @return \Illuminate\Database\Eloquent\Model
81+
*/
82+
public function createModel()
83+
{
84+
$this->auth->model();
85+
}
86+
}

0 commit comments

Comments
 (0)