petrsimunek / laravel-azure-middleware
Azure 中间件身份验证
Requires
- php: >=5.6.4
- guzzlehttp/guzzle: >=6.2
- laravel/framework: >=5.4.0
- microsoft/microsoft-graph: ^1.5
This package is auto-updated.
Last update: 2024-10-01 00:08:15 UTC
README
为 Laravel 应用提供 Azure 身份验证中间件。如果您喜欢这个项目,请查看 Laravel Saml 中间件
常规安装
composer require petrsimunek/laravel-azure-middleware
- 运行
php artisan vendor:publish --provider="petrsimunek\LaravelAzureMiddleware\AzureServiceProvider"
将配置文件安装到config/azure.php
- 在我们的路由文件夹(通常是
web.php
),添加
Route::get('/login/azure', '\petrsimunek\LaravelAzureMiddleware\Azure@azure') ->name('azure.login'); Route::get('/login/azurecallback', '\petrsimunek\LaravelAzureMiddleware\Azure@azurecallback') ->name('azure.callback');
注意:只有当在门户中配置
redirect_uri
时才需要路由名称。
- 在我们的
App\Http\Kernel.php
中添加'azure' => \petrsimunek\LaravelAzureMiddleware\Azure::class,
通常添加到$routeMiddleware
数组中。 - 在我们的
.env
中添加AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET 和 AZURE_RESOURCE
。我们可以在以下位置获取这些值/了解更多信息:https://portal.azure.com/(提示:AZURE_RESOURCE 应为 https://graph.microsoft.com) - 从 0.8.0 版本开始,我们添加了
AZURE_SCOPE
,这是用于请求的权限。我们可以在以下位置了解更多关于这些权限的信息:https://docs.microsoft.com/en-us/graph/api/resources/users?view=graph-rest-1.0 - 我们还添加了一个可选的
AZURE_DOMAIN_HINT
,可用于帮助用户知道他们应该使用哪个电子邮件地址进行登录。更多信息请参阅 https://azure.microsoft.com/en-us/updates/app-service-auth-and-azure-ad-domain-hints/ - 在我们的应用程序上 https://portal.azure.com/ 将
reply url
指向/login/azurecallback
路由,使用完整的 URL(例如:http://thewebsite.com/login/azurecallback)。 - 将
azure
中间件添加到需要受身份验证保护的任何路由的路由组中,享受 🎉 - 如果您需要自定义回调,请参阅 扩展安装。
注意:
您可能需要为(旧版)Azure Active Directory Graph 添加权限从 0.8.0 版本开始,我们使用 Azure 登录 API 的 v2 版本,这允许我们传递范围或我们希望使用的权限。
路由
Route::get('/login/azure', '\petrsimunek\LaravelAzureMiddleware\Azure@azure')->name('azure.login');
第一个参数可以指向您希望路由 Azure 登录的位置。根据需要更改。
Route::get('/login/azurecallback', '\petrsimunek\LaravelAzureMiddleware\Azure@azurecallback')->name('azure.callback');
第一个参数可以指向您希望回调后路由到的任何位置。根据需要更改。
Route::get('/logout/azure', '\petrsimunek\LaravelAzureMiddleware\Azure@azurelogout')->name('azure.logout);
第一个参数可以指向您希望回调后路由到的任何位置。根据需要更改。
注意:只有当在门户中配置
redirect_uri
时才需要路由名称。
前端
最好在登录网页上有一个指向 route('azure.login')
的 Office 365 按钮。这可以是一个简单的锚点标签,例如:<a href="{{ route('azure.login') }}" class="officeButton"></a>
扩展安装
开箱即用的实现允许您让用户登录。但是,假设我们想要将此用户存储到数据库中,并使用 Laravel Auth 登录用户。有两个建议从 Azure 类扩展的回调:名为 success
和 fail
。以下提供有关如何扩展 Root Laravel Azure Middleware Library 的信息
- 开始之前(假设我们已经按照常规安装说明操作),在
App\Http\Middleware
文件夹中创建一个名为AppAzure.php
的文件。您可以通过artisan
命令或手动操作来完成此操作。 - 在此文件中将以下内容作为起始点
<?php namespace App\Http\Middleware; use Illuminate\Http\Request; use petrsimunek\LaravelAzureMiddleware\Azure as Azure; use Microsoft\Graph\Graph; use Microsoft\Graph\Model; use Auth; use App\Models\User; class AppAzure extends Azure { protected function success(Request $request, $access_token, $refresh_token, $profile) { $graph = new Graph(); $graph->setAccessToken($access_token); $graph_user = $graph->createRequest("GET", "/me") ->setReturnType(Model\User::class) ->execute(); $email = strtolower($graph_user->getUserPrincipalName()); $user = User::updateOrCreate(['email' => $email], [ 'name' => $graph_user->getGivenName() . ' ' . $graph_user->getSurname(), ]); Auth::login($user, true); return parent::success($request, $access_token, $refresh_token, $profile); } }
以上方法为我们提供了一种在握手成功后添加/更新用户的方式。变量$profile
包含各种元数据,我们用它来创建或更新我们的用户。更多信息请参阅:https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code#jwt-token-claims。默认实现重定向到目标URL,或/
,因此在这里调用父类。您可以选择不扩展默认实现并重定向到其他地方。
- 我们需要更新以下路由
Route::get('/login/azure', '\App\Http\Middleware\AppAzure@azure') ->name('azure.login'); Route::get('/login/azurecallback', '\App\Http\Middleware\AppAzure@azurecallback') ->name('azure.callback'); Route::get('/logout/azure', '\App\Http\Middleware\AppAzure@azurelogout') ->name('azure.logout');
- 最后,将
Kernel.php
中的azure
键更新为'azure' => \App\Http\Middleware\AppAzure::class,
其他扩展选项
在每次握手时回调
从v0.4.0版本开始,我们在每次从Azure成功请求(握手)后添加了一个回调。默认操作是简单地调用$next
闭包。但是,假设我们想要更新用户。以下是如何进行操作的示例
<?php namespace App\Http\Middleware; use Illuminate\Http\Request; use Closure; use petrsimunek\LaravelAzureMiddleware\Azure as Azure; use Auth; use Carbon\Carbon; use App\User; class AppAzure extends Azure { protected function handlecallback(Request $request, Closure $next, $access_token, $refresh_token) { $user = Auth::user(); $user->updated_at = Carbon::now(); $user->save(); return parent::handlecallback($request, $next, $access_token, $refresh_token); } }
基于之前的扩展安装示例,现在Auth中有一个用户(因为我们成功回调中执行了Auth::login
)。利用用户模型,我们可以更新用户的updated_at
字段。回调应该调用闭包$next($request);
并返回它。在我们的情况下,默认实现就是这样做的,因此在这里调用父类。
自定义重定向
从v0.6.0版本开始,我们添加了自定义重定向方法的功能。例如,如果会话令牌已过期,但用户仍然通过Laravel进行身份验证,我们可以用以下示例进行检查
<?php namespace App\Http\Middleware; use Illuminate\Http\Request; use petrsimunek\LaravelAzureMiddleware\Azure as Azure; use Auth; class AppAzure extends Azure { protected function redirect(Request $request) { if (Auth::user() !== null) { return $this->azure($request); } else { return parent::redirect($request); } } }
不同的登录路由
从v0.4.0版本开始,我们添加了更改中间件中的$login_route
的能力。基于扩展安装,在我们的AppAzure
类中,我们可以简单地设置$login_route
为任何值。例如
<?php namespace App\Http\Middleware; use petrsimunek\LaravelAzureMiddleware\Azure as Azure; class AppAzure extends Azure { protected $login_route = "/"; }
以上将$login_route
设置为/
或根目录。
获取/重写Azure路由
从v0.7.0版本开始,我们添加了获取Azure URL的能力。例如,假设我们想要修改Azure URL,使其将用户的电子邮件作为参数传递给Azure。基于扩展安装,在我们的AppAzure
类中,我们可以这样做
<?php namespace App\Http\Middleware; use Illuminate\Http\Request; use petrsimunek\LaravelAzureMiddleware\Azure as Azure; use Auth; class AppAzure extends Azure { //we could overload this if we wanted too. public function getAzureUrl() { $url = $this->baseUrl . config('azure.tenant_id') . $this->route2 . "authorize?response_type=code&client_id=" . config('azure.client.id') . "&domain_hint=" . urlencode(config('azure.domain_hint')) . "&scope=" . urldecode(config('azure.scope')); return Route::has('azure.callback') ? $url . '&redirect_uri=' . urlencode(route('azure.callback')) : $url; } public function azure(Request $request) { $user = Auth::user(); $away = $this->getAzureUrl(); if ($user) { $away .= "&login_hint=" . $user->email; } return redirect()->away($away); } }
在多租户应用程序中使用
如果所需的用例需要多租户应用程序,您只需在.env文件中提供common
而不是租户ID即可。例如:AZURE_TENANT_ID=common
。
这通过将您的最终用户发送到Microsoft提供的通用登录路由来完成,从开发的角度来看,这看起来应该没有太大区别。应该知道,这种方法的潜在缺点已在MS Dev文档中提及
当单个租户应用程序验证令牌时,它会将令牌签名与元数据文档中的签名密钥进行比较。此测试允许它确保令牌中的发行者值与元数据文档中找到的值匹配。因为/common端点不对应于任何租户,也不是发行者,所以当您检查/common的元数据中的发行者值时,它有一个模板URL而不是实际值...
有关此信息的更多信息,请参阅此处。
使用Laravel Azure Middleware进行测试
自v0.7.0版本起,我们通过调用actingAs
为HTTP测试或使用Dusk的loginAs
与Laravel测试进行集成。这假设我们在成功回调中使用Auth::login
方法,如扩展安装中所示。在AppAzure
类中无需进行任何操作,除非我们需要覆盖默认行为,如下所示
<?php namespace App\Http\Middleware; use Illuminate\Http\Request; use petrsimunek\LaravelAzureMiddleware\Azure as Azure; use Auth; class AppAzure extends Azure { //this is the default behavior //overwrite to meet your needs protected function handleTesting(Request $request, Closure $next) { $user = Auth::user(); if (!isset($user)) { return $this->redirect($request, $next); } return $this->handlecallback($request, $next, null, null); } }
上述代码将调用类的重定向方法,如果它无法在Laravel的认证中找到用户。否则,上述代码将调用类的handlecallback方法。因此,测试可以检查是否发生了正确的重定向,或者handlecallback是否正常工作(默认情况下调用$next($request);
)。
贡献
感谢您考虑为Laravel Azure Middleware做出贡献!为了鼓励积极的协作,我们鼓励提交pull请求,而不仅仅是问题报告。
如果您提交问题,问题应该包含标题和问题清晰的描述。您还应该包括尽可能多的相关信息和一个演示问题的代码示例。问题的目标是让您和其他人能够轻松地复现错误并开发解决方案。
许可证
Laravel Azure Middleware是开源软件,许可协议为MIT许可证。