mirror of
https://github.com/grocy/grocy.git
synced 2026-04-04 20:06:16 +02:00
add OAuthMiddleware
This commit is contained in:
parent
1616b41ea9
commit
84edcd7f3d
|
|
@ -96,6 +96,15 @@ Setting('LDAP_BIND_PW', ''); // Password for the above account
|
||||||
Setting('LDAP_USER_FILTER', ''); // Example value "(OU=grocy_users)"
|
Setting('LDAP_USER_FILTER', ''); // Example value "(OU=grocy_users)"
|
||||||
Setting('LDAP_UID_ATTR', ''); // Windows AD: "sAMAccountName", OpenLDAP: "uid", GLAuth: "cn"
|
Setting('LDAP_UID_ATTR', ''); // Windows AD: "sAMAccountName", OpenLDAP: "uid", GLAuth: "cn"
|
||||||
|
|
||||||
|
// Options when using OAuthMiddleware
|
||||||
|
Setting('OAUTH_CLIENT_ID', '');
|
||||||
|
Setting('OAUTH_CLIENT_SECRET', '');
|
||||||
|
Setting('OAUTH_SCOPES', 'openid profile');
|
||||||
|
Setting('OAUTH_USERNAME_CLAIM', 'preferred_username');
|
||||||
|
Setting('OAUTH_AUTH_URL', '');
|
||||||
|
Setting('OAUTH_TOKEN_URL', '');
|
||||||
|
Setting('OAUTH_USERINFO_URL', '');
|
||||||
|
|
||||||
// Default permissions for new users
|
// Default permissions for new users
|
||||||
// the array needs to contain the technical/constant names
|
// the array needs to contain the technical/constant names
|
||||||
// See the file controllers/Users/User.php for possible values
|
// See the file controllers/Users/User.php for possible values
|
||||||
|
|
|
||||||
109
middleware/OAuthMiddleware.php
Normal file
109
middleware/OAuthMiddleware.php
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Grocy\Middleware;
|
||||||
|
|
||||||
|
use DI\Container;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\RequestOptions;
|
||||||
|
use Grocy\Services\DatabaseService;
|
||||||
|
use Grocy\Services\UsersService;
|
||||||
|
use Grocy\Services\SessionService;
|
||||||
|
use Psr\Http\Message\ResponseFactoryInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* minimalistic OAuth middleware
|
||||||
|
*/
|
||||||
|
class OAuthMiddleware extends AuthMiddleware
|
||||||
|
{
|
||||||
|
private Client $client;
|
||||||
|
|
||||||
|
public function __construct(Container $container, ResponseFactoryInterface $responseFactory)
|
||||||
|
{
|
||||||
|
parent::__construct($container, $responseFactory);
|
||||||
|
|
||||||
|
$this->client = new Client(['timeout' => 2.0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authenticate(Request $request)
|
||||||
|
{
|
||||||
|
define('GROCY_EXTERNALLY_MANAGED_AUTHENTICATION', true);
|
||||||
|
|
||||||
|
// First try to authenticate by API key
|
||||||
|
$auth = new ApiKeyAuthMiddleware($this->AppContainer, $this->ResponseFactory);
|
||||||
|
$user = $auth->authenticate($request);
|
||||||
|
if ($user !== null)
|
||||||
|
{
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then by session cookie
|
||||||
|
$auth = new SessionAuthMiddleware($this->AppContainer, $this->ResponseFactory);
|
||||||
|
$user = $auth->authenticate($request);
|
||||||
|
if ($user !== null)
|
||||||
|
{
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no active session -> start OAuth flow
|
||||||
|
// 1. redirect to auth URL (only if code parameter not already set)
|
||||||
|
$code = $request->getQueryParam('code');
|
||||||
|
if ($code === null) {
|
||||||
|
$response = $this->ResponseFactory->createResponse();
|
||||||
|
if (string_starts_with($request->getUri()->getPath(), '/api/')) {
|
||||||
|
// no OAuth for API calls
|
||||||
|
return $response->withStatus(401);
|
||||||
|
} else {
|
||||||
|
return $response->withRedirect(
|
||||||
|
GROCY_OAUTH_AUTH_URL .
|
||||||
|
"?response_type=code" .
|
||||||
|
"&client_id=" . GROCY_OAUTH_CLIENT_ID .
|
||||||
|
"&redirect_uri=" . $request->getUri() .
|
||||||
|
"&scope=" . GROCY_OAUTH_SCOPES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. handle callback from auth server
|
||||||
|
// -> code parameter given to get token from aut server
|
||||||
|
$tokenResponse = $this->client->request('POST', GROCY_OAUTH_TOKEN_URL, [
|
||||||
|
RequestOptions::AUTH => [GROCY_OAUTH_CLIENT_ID, GROCY_OAUTH_CLIENT_SECRET],
|
||||||
|
RequestOptions::FORM_PARAMS => [
|
||||||
|
"grant_type" => "authorization_code",
|
||||||
|
"code" => $code,
|
||||||
|
"redirect_uri" => (string)$request->getUri(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
if ($tokenResponse->getStatusCode() != 200) {
|
||||||
|
throw new \Exception('token request failed. Status code: ' . $response->getStatusCode());
|
||||||
|
}
|
||||||
|
$tokenResponseJson = json_decode($tokenResponse->getBody(), true);
|
||||||
|
|
||||||
|
// auth successful -> start collection user information
|
||||||
|
$infoResponse = $this->client->request('POST', GROCY_OAUTH_USERINFO_URL, [
|
||||||
|
RequestOptions::HEADERS => [
|
||||||
|
"Authorization" => "Bearer " . $tokenResponseJson["access_token"]
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
if ($infoResponse->getStatusCode() != 200) {
|
||||||
|
throw new \Exception('user info request failed error: ' . $response->getStatusCode());
|
||||||
|
}
|
||||||
|
$infoResponseJson = json_decode($infoResponse->getBody(), true);
|
||||||
|
|
||||||
|
// get user from database or create one if needed
|
||||||
|
$db = DatabaseService::getInstance()->GetDbConnection();
|
||||||
|
$user = $db->users()->where('username', $infoResponseJson[GROCY_OAUTH_USERNAME_CLAIM])->fetch();
|
||||||
|
if ($user == null) {
|
||||||
|
$user = UsersService::getInstance()->CreateUser($infoResponseJson[GROCY_OAUTH_USERNAME_CLAIM], '', '', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
self::SetSessionCookie(SessionService::getInstance()->CreateSession($user->id, false));
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function ProcessLogin(array $postParams)
|
||||||
|
{
|
||||||
|
throw new \Exception('Not implemented');
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user