datamweb / shield-oauth Goto Github PK
View Code? Open in Web Editor NEWOAuth for CodeIgniter Shield
Home Page: https://www.shield-oauth.codeigniter4.ir/
License: MIT License
OAuth for CodeIgniter Shield
Home Page: https://www.shield-oauth.codeigniter4.ir/
License: MIT License
8.2
4.3.3
latest dev
dev-develop
Linux
fpm-fcgi
Mariadb 10.6
No
if there is another user with the same username, an error occurs when registering a new account with google login.
duplicate username error
CodeIgniter\Database\Exceptions\DatabaseException #1062
Duplicate entry 'Glad' for key 'username'
SYSTEMPATH/Database/BaseBuilder.php : 2309 — CodeIgniter\Database\BaseConnection->query ()
2302 array_keys($this->QBSet),
2303 array_values($this->QBSet)
2304 );
2305
2306 if (! $this->testMode) {
2307 $this->resetWrite();
2308
2309 $result = $this->db->query($sql, $this->binds, false);
2310
2311 // Clear our binds so we don't eat up memory
2312 $this->binds = [];
2313
2314 return $result;
2315 }
2316
SYSTEMPATH/Model.php : 330 — CodeIgniter\Database\BaseBuilder->insert ()
323 );
324 } else {
325 $sql = 'INSERT INTO ' . $table . ' DEFAULT VALUES';
326 }
327
328 $result = $this->db->query($sql);
329 } else {
330 $result = $builder->insert();
331 }
332
333 // If insertion succeeded then save the insert ID
334 if ($result) {
335 $this->insertID = ! $this->useAutoIncrement ? $data[$this->primaryKey] : $this->db->insertID();
336 }
337
SYSTEMPATH/BaseModel.php : 782 — CodeIgniter\Model->doInsert ()
775
776 $eventData = ['data' => $data];
777
778 if ($this->tempAllowCallbacks) {
779 $eventData = $this->trigger('beforeInsert', $eventData);
780 }
781
782 $result = $this->doInsert($eventData['data']);
783
784 $eventData = [
785 'id' => $this->insertID,
786 'data' => $eventData['data'],
787 'result' => $result,
788 ];
789
SYSTEMPATH/Model.php : 730 — CodeIgniter\BaseModel->insert ()
723 $this->tempPrimaryKeyValue = $data->{$this->primaryKey};
724 }
725 }
726
727 $this->escape = $this->tempData['escape'] ?? [];
728 $this->tempData = [];
729
730 return parent::insert($data, $returnID);
731 }
732
733 /**
734 * Updates a single record in the database. If an object is provided,
735 * it will attempt to convert it into an array.
736 *
737 * @param array|int|string|null $id
VENDORPATH/codeigniter4/shield/src/Models/UserModel.php : 253 — CodeIgniter\Model->insert ()
246 * @throws ValidationException
247 */
248 public function insert($data = null, bool $returnID = true)
249 {
250 // Clone User object for not changing the passed object.
251 $this->tempUser = $data instanceof User ? clone $data : null;
252
253 $result = parent::insert($data, $returnID);
254
255 $this->checkQueryReturn($result);
256
257 return $returnID ? $this->insertID : $result;
258 }
259
260 /**
SYSTEMPATH/BaseModel.php : 692 — CodeIgniter\Shield\Models\UserModel->insert ()
685 if (empty($data)) {
686 return true;
687 }
688
689 if ($this->shouldUpdate($data)) {
690 $response = $this->update($this->getIdValue($data), $data);
691 } else {
692 $response = $this->insert($data, false);
693
694 if ($response !== false) {
695 $response = true;
696 }
697 }
698
699 return $response;
VENDORPATH/codeigniter4/shield/src/Models/UserModel.php : 315 — CodeIgniter\BaseModel->save ()
308 *
309 * @return true if the save is successful
310 *
311 * @throws ValidationException
312 */
313 public function save($data): bool
314 {
315 $result = parent::save($data);
316
317 $this->checkQueryReturn($result);
318
319 return true;
320 }
321
322 /**
VENDORPATH/datamweb/shield-oauth/src/Controllers/OAuthController.php : 88 — CodeIgniter\Shield\Models\UserModel->save ()
81
82 if ($this->checkExistenceUser($find) === false) {
83 helper('text');
84 $users = model('ShieldOAuthModel');
85 // new user
86 $entitiesUser = new User($oauthClass->getColumnsName('newUser', $userInfo));
87
88 $users->save($entitiesUser);
89 $userid = $users->getInsertID();
90 // To get the complete user object with ID, we need to get from the database
91 $user = $users->findById($userid);
92 $users->save($user);
93 // Add to default group
94 $users->addToDefaultGroup($user);
95 }
SYSTEMPATH/CodeIgniter.php : 934 — Datamweb\ShieldOAuth\Controllers\OAuthController->callBack ()
927 protected function runController($class)
928 {
929 // This is a Web request or PHP CLI request
930 $params = $this->router->params();
931
932 $output = method_exists($class, '_remap')
933 ? $class->_remap($this->method, ...$params)
934 : $class->{$this->method}(...$params);
935
936 $this->benchmark->stop('controller');
937
938 return $output;
939 }
940
941 /**
SYSTEMPATH/CodeIgniter.php : 499 — CodeIgniter\CodeIgniter->runController ()
492 if (! method_exists($controller, '_remap') && ! is_callable([$controller, $this->method], false)) {
493 throw PageNotFoundException::forMethodNotFound($this->method);
494 }
495
496 // Is there a "post_controller_constructor" event?
497 Events::trigger('post_controller_constructor');
498
499 $returned = $this->runController($controller);
500 } else {
501 $this->benchmark->stop('controller_constructor');
502 $this->benchmark->stop('controller');
503 }
504
505 // If $returned is a string, then the controller output something,
506 // probably a view, instead of echoing it directly. Send it along
SYSTEMPATH/CodeIgniter.php : 368 — CodeIgniter\CodeIgniter->handleRequest ()
361 $this->response->send();
362 $this->callExit(EXIT_SUCCESS);
363
364 return;
365 }
366
367 try {
368 return $this->handleRequest($routes, $cacheConfig, $returnResponse);
369 } catch (RedirectException $e) {
370 $logger = Services::logger();
371 $logger->info('REDIRECTED ROUTE at ' . $e->getMessage());
372
373 // If the route is a 'redirect' route, it throws
374 // the exception with the $to as the message
375 $this->response->redirect(base_url($e->getMessage()), 'auto', $e->getCode());
FCPATH/index.php : 67 — CodeIgniter\CodeIgniter->run ()
60 *---------------------------------------------------------------
61 * LAUNCH THE APPLICATION
62 *---------------------------------------------------------------
63 * Now that everything is setup, it's time to actually fire
64 * up the engines and make this app do its thang.
65 */
66
67 $app->run();
68
Manually register a user using Shield with the first name of a test gmail user, eg John. Then log in with a test Gmail account whose user is named John. This will generate a duplicate username error.
It was expected that the username would be registered with some suffix to differentiate it from an existing user.
No response
8.2.5
4.3.6
beta
dev-main
Linux
apache
5.7.33
NO
I'm trying to use google oauth and I got the error:
92 : HTTP/2 stream 0 was not closed cleanly: INTERNAL_ERROR (err 2)
I tried using Google's login button
working
No response
Hi all,
I've added a Microsoft OAuth service and i would like to share with community.
I take this opportunity to request that it be made configurable whether or not new users can be registered
Here are de code :)
config file: App\Config\ShieldOAuthConfig.php
<?php
public array $oauthConfigs = [
'microsoft' => [
'client_id' => 'Get it from Microsoft Entra ID',
'client_secret' => 'Get it from Microsoft Entra ID',
'allow_login' => true,
],
];
library file: App\Libraries\ShieldOAuth\MicrosoftOAuth.php
<?php
declare(strict_types=1);
namespace App\Libraries\ShieldOAuth;
use Datamweb\ShieldOAuth\Libraries\Basic\AbstractOAuth;
use Exception;
use stdClass;
class MicrosoftOAuth extends AbstractOAuth
{
private static $API_CODE_URL = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize';
private static $API_TOKEN_URL = 'https://login.microsoftonline.com/common/oauth2/token';
private static $API_USER_INFO_URL = 'https://graph.microsoft.com/v1.0/me';
private static $APPLICATION_NAME = 'ShieldOAuth';
protected string $token;
protected $client;
protected $config;
protected string $client_id;
protected string $client_secret;
protected string $callback_url;
public function __construct(string $token = '')
{
$this->token = $token;
$this->client = \Config\Services::curlrequest();
$this->config = new \Config\ShieldOAuthConfig();
$this->callback_url = base_url('oauth/' . $this->config->call_back_route);
$this->client_id = env('ShieldOAuthConfig.microsoft.client_id', $this->config->oauthConfigs['microsoft']['client_id']);
$this->client_secret = env('ShieldOAuthConfig.microsoft.client_secret', $this->config->oauthConfigs['microsoft']['client_secret']);
}
public function makeGoLink(string $state): string
{
try
{
if (empty($this->client_id))
{
throw new Exception('Microsoft Tenant ID is empty,');
}
if (empty($this->client_id))
{
throw new Exception('Microsoft Client ID is empty,');
}
if (empty($this->client_secret))
{
throw new Exception('Microsoft Secret is empty,');
}
$query = http_build_query([
'client_id' => $this->client_id,
'response_type' => 'code',
'redirect_uri' => $this->callback_url,
'response_mode' => 'query',
'approval_prompt' => 'auto',
'scope' => 'User.Read profile openid email',
'state' => $state
]);
$microsoftURL = self::$API_CODE_URL . '?' . $query;
return $microsoftURL;
}
catch (\Throwable $e)
{
die($e->getMessage());
}
}
public function fetchAccessTokenWithAuthCode(array $allGet): void
{
$client = \Config\Services::curlrequest();
try
{
$response = $client->request('POST', self::$API_TOKEN_URL, [
'form_params' => [
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'grant_type' => 'authorization_code',
'redirect_uri' => $this->callback_url,
'code' => $allGet['code']
],
'http_errors' => false,
]);
$response = json_decode($response->getBody());
if (!empty($response->error))
{
throw new Exception($response->error);
}
$this->setToken($response->access_token);
}
catch (Exception $e)
{
die($e->getMessage());
}
}
public function fetchUserInfoWithToken(): object
{
try
{
$response = $this->client->request('GET', self::$API_USER_INFO_URL, [
'headers' => [
'Authorization' => 'Bearer ' . $this->getToken(),
],
'http_errors' => false,
]);
}
catch (Exception $e)
{
die($e->getMessage());
}
$response = json_decode($response->getBody());
$userInfo = new stdClass();
$userInfo->username = $response->userPrincipalName;
$userInfo->email = $response->mail;
$userInfo->first_name = $response->givenName;
$userInfo->last_name = $response->surname;
$userInfo->avatar = '';
return $userInfo;
}
public function setColumnsName(string $nameOfProcess, object $userInfo): array
{
if ($nameOfProcess === 'syncingUserInfo')
{
$usersColumnsName = [
$this->config->usersColumnsName['first_name'] => $userInfo->first_name,
$this->config->usersColumnsName['last_name'] => $userInfo->last_name,
//$this->config->usersColumnsName['avatar'] => $userInfo->last_name, // No get avantar from request
];
}
if ($nameOfProcess === 'newUser')
{
die('Auto-register users is disabled;');
// Commented because i not use register new users
// $usersColumnsName = [
// 'username' => $userInfo->username,
// 'email' => $userInfo->email,
// 'password' => random_string('crypto', 32),
// 'active' => TRUE,
// $this->config->usersColumnsName['first_name'] => $userInfo->first_name,
// $this->config->usersColumnsName['last_name'] => $userInfo->last_name,
// $this->config->usersColumnsName['avatar'] => $userInfo->avatar,
// ];
}
return $usersColumnsName;
}
}
8.3
4.4.8
1.0.2
dev-develop
macOS
cli-server (PHP built-in webserver)
PostgreSQL 15.4
No
when logging in using google oauth I got the error as follow:
Undefined property: stdClass:: $family_name
click google-oauth button
because the family name property was not found, perhaps it could be replaced with the given_name property or not include both because it is already represented by the name property
No response
8.2.6
4.3.4
dev-develop
dev-main
Windows
cli
MySQL 8.0.33
No
D:\www\mobileproxy>php spark shield:model UserModel
CodeIgniter v4.3.5 Command Line Tool - Server Time: 2023-05-23 01:15:15 UTC+00:00
[ErrorException]
foreach() argument must be of type array|object, string given
at VENDORPATH\datamweb\shield-oauth\src\Libraries\Basic\ShieldOAuth.php:86
Backtrace:
1 VENDORPATH\datamweb\shield-oauth\src\Libraries\Basic\ShieldOAuth.php:86
CodeIgniter\Debug\Exceptions()->errorHandler(2, 'foreach() argument must be of type array|object, string given', 'D:\\www\\mobileproxy\\vendor\\datamweb\\shield-oauth\\src\\Libraries\\Basic\\ShieldOAuth.php', 86)
2 VENDORPATH\datamweb\shield-oauth\src\Libraries\Basic\ShieldOAuth.php:111
Datamweb\ShieldOAuth\Libraries\Basic\ShieldOAuth()->otherOAuth()
3 VENDORPATH\datamweb\shield-oauth\src\Views\Decorators\ShieldOAuth.php:21
Datamweb\ShieldOAuth\Libraries\Basic\ShieldOAuth()->makeOAuthButton('login')
4 SYSTEMPATH\View\ViewDecoratorTrait.php:31
Datamweb\ShieldOAuth\Views\Decorators\ShieldOAuth::decorate('<@php
declare(strict_types=1);
namespace {namespace};
use CodeIgniter\\Shield\\Models\\UserModel as ShieldUserModel;
class {class} extends ShieldUserModel
{
protected function initialize(): void
{
parent::initialize();
$this->allowedFields = [
...$this->allowedFields,
// \'first_name\',
];
}
}')
5 SYSTEMPATH\View\View.php:234
CodeIgniter\View\View()->decorateOutput('<@php
declare(strict_types=1);
namespace {namespace};
use CodeIgniter\\Shield\\Models\\UserModel as ShieldUserModel;
class {class} extends ShieldUserModel
{
protected function initialize(): void
{
parent::initialize();
$this->allowedFields = [
...$this->allowedFields,
// \'first_name\',
];
}
}')
6 SYSTEMPATH\Common.php:1184
CodeIgniter\View\View()->render('CodeIgniter\\Commands\\Generators\\Views\\usermodel.tpl.php', [...], true)
7 SYSTEMPATH\CLI\GeneratorTrait.php:274
view('CodeIgniter\\Commands\\Generators\\Views\\usermodel.tpl.php', [], [...])
8 SYSTEMPATH\CLI\GeneratorTrait.php:292
CodeIgniter\Shield\Commands\Generators\UserModelGenerator()->renderTemplate([])
9 SYSTEMPATH\CLI\GeneratorTrait.php:204
CodeIgniter\Shield\Commands\Generators\UserModelGenerator()->parseTemplate('App\\Models\\UserModel')
10 SYSTEMPATH\CLI\GeneratorTrait.php:302
CodeIgniter\Shield\Commands\Generators\UserModelGenerator()->prepare('App\\Models\\UserModel')
11 SYSTEMPATH\CLI\GeneratorTrait.php:115
CodeIgniter\Shield\Commands\Generators\UserModelGenerator()->buildContent('App\\Models\\UserModel')
12 SYSTEMPATH\CLI\GeneratorTrait.php:94
CodeIgniter\Shield\Commands\Generators\UserModelGenerator()->generateClass([...])
13 VENDORPATH\codeigniter4\shield\src\Commands\Generators\UserModelGenerator.php:77
CodeIgniter\Shield\Commands\Generators\UserModelGenerator()->execute([...])
14 SYSTEMPATH\CLI\Commands.php:65
CodeIgniter\Shield\Commands\Generators\UserModelGenerator()->run([...])
15 SYSTEMPATH\CLI\Console.php:37
CodeIgniter\CLI\Commands()->run('shield:model', [...])
16 ROOTPATH\spark:97
CodeIgniter\CLI\Console()->run()
Open CMD
php spark shield:model UserModel
No response
8.1.23
4.4.1
dev-develop
dev-main
macOS
apache
mysql:latest
no, just Google
On oauth/call-back i got an error:
Typed property CodeIgniter\Shield\Models\BaseModel::$tables must not be accessed before initialization
VENDORPATH/codeigniter4/shield/src/Models/UserModel.php at line 196
194 if ($email !== null) {
195 $data = $this->select(
196 sprintf('%1$s.*, %2$s.secret as email, %2$s.secret2 as password_hash', $this->table, $this->tables['identities'])
197 )
i think thats because $this->tables is null which - i believe - is because we're not initializing parent in ShieldOAuthModel
just regular setup according to repo guide
one should be logged in (or not)
No response
8.1
4.3.2
1.0.0-beta.3
dev-develop
Windows
apache
MySQL 5.6
YES.
It's not public
When signing in with google or github, using the email as authentication identity is fine, but when you add facebook for example, it already breaks, since facebook doesnt always have an email available. A more reliable way would be to use the id, and only pull the email if available
Use the facebook OAuth available in the discussions, and try signing in with a fb account where you used phone number to sign in
To be able to sign in without unexpected error
I hope i managed to make it as clear as possible, but if not, let me know, and will try to add some sources for explanation
Hello,
In all my ci4 projects I try not to use the "app" folder, what I do is create a "modules" folder and then one for the module in question.
In this case, I have a module called "Auth", which is located in "./modules/Auth/" and there I have the Shield customizations and it works perfect.
I have also tried to put the Shield OAuth customizations, but I see that it does not work, looking at the code I see that it looks for the files within app/Config.
Is it possible to use Shield OAuth within a module?
Example of my folder esctructure:
Clean code is an important part of programming, so I try to add the following tools to the shield-oauth
for extensibility, cleanliness and reliability.
Any person who has the experience of using or solving problems can help in this matter.
Command php spark make:oauth newOAuth
allows the user to perform all the steps described in add-new-oauth-to-shield-oauth through the terminal.
After successfully authenticating Google account, when I reach "https://localhost:8000/oauth/call-back" I get this error:
CodeIgniter\HTTP\Exceptions\HTTPException
92 : HTTP/2 stream 0 was not closed cleanly: Unknown error code (err 2)
I am not facing any such issue with Github authentication. It is only with Google.
CRITICAL - 2022-11-01 15:36:01 --> foreach() argument must be of type array|object, string given
in VENDORPATH\datamweb\shield-oauth\src\Libraries\Basic\ShieldOAuth.php on line 86.
1 VENDORPATH\datamweb\shield-oauth\src\Libraries\Basic\ShieldOAuth.php(86): CodeIgniter\Debug\Exceptions->errorHandler(2, 'foreach() argument must be of type array|object, string given', 'VENDORPATH\\datamweb\\shield-oauth\\src\\Libraries\\Basic\\ShieldOAuth.php', 86)
2 VENDORPATH\datamweb\shield-oauth\src\Libraries\Basic\ShieldOAuth.php(111): Datamweb\ShieldOAuth\Libraries\Basic\ShieldOAuth->otherOAuth()
shield-oauth/src/Libraries/Basic/ShieldOAuth.php
Lines 81 to 95 in 071a8bc
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.