Skip to content

Commit

Permalink
Merge pull request #1338 from bakaphp/feat-auth-device-id
Browse files Browse the repository at this point in the history
refact: two party auth per device
  • Loading branch information
kaioken authored May 16, 2024
2 parents ff3e6ef + 7acf439 commit 998de7b
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,19 @@ public function loginMutation(
): array {
$email = $request['data']['email'];
$password = $request['data']['password'];
$deviceId = $request['data']['device_id'] ?? null;
$request = request();

$user = $this->login(
LoginInput::from([
'email' => $email,
'password' => $password,
'ip' => $request->ip(),
'deviceId' => $deviceId
])
);

return $user->createToken('kanvas-login')->toArray();
return $user->createToken(name: 'kanvas-login', deviceId: $deviceId)->toArray();
}

/**
Expand Down Expand Up @@ -173,7 +175,7 @@ public function socialLogin(mixed $root, array $req): array
$socialLogin = new SocialLoginAction($user, $provider);

$loggedUser = $socialLogin->execute();
$tokenResponse = $loggedUser->createToken('kanvas-login')->toArray();
$tokenResponse = $loggedUser->createToken(name: 'kanvas-login')->toArray();

return $tokenResponse;
}
Expand Down
15 changes: 15 additions & 0 deletions app/GraphQL/Ecosystem/Mutations/Users/TwoFactorAuthMutation.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Kanvas\Connectors\Twilio\Client;
use Kanvas\Connectors\Twilio\Enums\ConfigurationEnum;
use Kanvas\Exceptions\ValidationException;
use Kanvas\Users\Enums\UserConfigEnum;

use function Sentry\captureException;

Expand Down Expand Up @@ -79,4 +80,18 @@ public function verifyCode($rootValue, array $request): bool

return false;
}

public function setToggleTwoFactorAuthIn30Days($rootValue, array $request): bool
{
$user = auth()->user();
$app = app(Apps::class);

$key = UserConfigEnum::TWO_FACTOR_AUTH_30_DAYS->value . '-' . $user->getCurrentDeviceId();

if ($request['active']) {
return $user->set($key, (int) $request['active']);
}

return $user->del($key);
}
}
5 changes: 5 additions & 0 deletions graphql/schemas/Ecosystem/user.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ extend type Mutation {
@field(
resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Users\\UserManagementMutation@updatePhotoProfile"
)
setToggleTwoFactorAuthIn30Days(active: Boolean!): Boolean!
@guard
@field(
resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Users\\TwoFactorAuthMutation@setToggleTwoFactorAuthIn30Days"
)
}

type Query @guard {
Expand Down
2 changes: 1 addition & 1 deletion graphql/schemas/Guild/lead.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type Lead {
stage: LeadPipelineStage @belongsTo(relation: "stage")
participants: [LeadsParticipants!]! @hasMany
channels: [SocialChannel]! @hasMany(relation: "socialChannels")
systemModule: SystemModule!
systemModule: SystemModule
files: [Filesystem!]!
@paginate(
defaultCount: 25
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function getInventoryId(Regions $region): int|string|null
};
}

public function getShopifyUrl(Regions $region): string
public function getShopifyUrl(Regions $region): ?string
{
$key = CustomFieldEnum::SHOPIFY_PRODUCT_URL->value . '-' . $region->getId();

Expand Down
1 change: 1 addition & 0 deletions src/Kanvas/Auth/DataTransferObject/LoginInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function __construct(
public string $email,
public string $password,
public string $ip,
public ?string $deviceId = null
) {
}

Expand Down
3 changes: 2 additions & 1 deletion src/Kanvas/Auth/Jwt.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static function getConfig(): Configuration
*
* @return Plain
*/
public static function createToken(string $sessionId, string $email, float $expirationAt = 0): Plain
public static function createToken(string $sessionId, string $email, float $expirationAt = 0, ?string $deviceId = null): Plain
{
$now = new DateTimeImmutable();
$config = self::getConfig();
Expand All @@ -56,6 +56,7 @@ public static function createToken(string $sessionId, string $email, float $expi
->expiresAt($now->modify('+' . $expiration . ' hour'))
->withClaim('sessionId', $sessionId)
->withClaim('email', $email)
->withClaim('deviceId', $deviceId)
// Builds a new token
->getToken($config->signer(), $config->signingKey());
}
Expand Down
7 changes: 6 additions & 1 deletion src/Kanvas/Auth/TokenGuard.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,23 @@ protected function sessionUser(Token $token, Request $request): Users

if (! empty($token->claims()->get('sessionId'))) {
$userSession = $session->getById($token->claims()->get('sessionId'), $app);
$tokenDeviceId = $token->claims()->get('deviceId');

if (! $user = $userSession->user()->first()) {
throw new AuthorizationException('Session User not found');
}

return $session->check(
$sessionUser = $session->check(
$user,
$token->claims()->get('sessionId'),
(string) $request->ip(),
app(Apps::class),
1
);

$sessionUser->setCurrentDeviceId($tokenDeviceId);

return $sessionUser;
} else {
throw new AuthorizationException('Session User not found');
}
Expand Down
7 changes: 4 additions & 3 deletions src/Kanvas/Auth/Traits/HasJwtToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ trait HasJwtToken
public function createToken(
string $name,
array $abilities = ['*'],
?DateTimeInterface $expiresAt = null
?DateTimeInterface $expiresAt = null,
?string $deviceId = null
): NewAccessToken {
$userIp = request()->ip();
$pageId = 1;

$sessionId = (string)Str::uuid();
$tokenResponse = Jwt::createToken($sessionId, $this->email);
$tokenResponse = Jwt::createToken($sessionId, $this->email, 0, $deviceId);
$monthInHours = ceil((config('kanvas.jwt.payload.refresh_exp') ?? 2628000) / 3600);
$refreshToken = Jwt::createToken($sessionId, $this->email, $monthInHours);
$refreshToken = Jwt::createToken($sessionId, $this->email, $monthInHours, $deviceId);

//start session
$session = new Sessions();
Expand Down
18 changes: 15 additions & 3 deletions src/Kanvas/Users/Models/Users.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class Users extends Authenticatable implements UserInterface, ContractsAuthentic
use CanUseWorkflow;

protected ?string $defaultCompanyName = null;
protected ?string $currentDeviceId = null;

protected $guarded = [];

Expand Down Expand Up @@ -691,15 +692,16 @@ public function getAppIsActive(): bool
public function runVerifyTwoFactorAuth(?AppInterface $app = null): bool
{
$user = $this->getAppProfile($app ?? app(Apps::class));
$twoFactorKey = UserConfigEnum::TWO_FACTOR_AUTH_30_DAYS->value . '-' . $this->getCurrentDeviceId();

if (! $this->get(UserConfigEnum::TWO_FACTOR_AUTH_30_DAYS->value) && $user->phone_verified_at && now()->subDays(7)->lte(new Carbon($user->phone_verified_at))) {
return false;
if (! $this->get($twoFactorKey) && $user->phone_verified_at && now()->subDays(7)->lte(new Carbon($user->phone_verified_at))) {
// return false;
}

/**
* @todo user config per app
*/
return ! ($this->get(UserConfigEnum::TWO_FACTOR_AUTH_30_DAYS->value)
return ! ((bool) $this->get($twoFactorKey)
&& $user->phone_verified_at && now()->subDays(30)->lte(new Carbon($user->phone_verified_at)));
}

Expand Down Expand Up @@ -758,4 +760,14 @@ public static function search($query = '', $callback = null)

return $query;
}

public function setCurrentDeviceId(string $deviceId): void
{
$this->currentDeviceId = $deviceId;
}

public function getCurrentDeviceId(): string
{
return $this->currentDeviceId;
}
}
3 changes: 2 additions & 1 deletion tests/Connectors/Integration/Shopify/VariantTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,11 @@ public function testSetImage()


$shopifyProduct = $shopify->saveProduct($product, StatusEnum::ACTIVE);
$url = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png';

foreach ($product->variants as $variant) {
$shopify->saveVariant($variant);
$shopifyVariantResponse = $shopify->addImages($variant, fake()->imageUrl(640, 480, 'animals', true));
$shopifyVariantResponse = $shopify->addImages($variant, $url);

$this->assertEquals(
$variant->image,
Expand Down

0 comments on commit 998de7b

Please sign in to comment.