6
.gitattributes
vendored
@@ -2,10 +2,12 @@
|
|||||||
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
|
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
|
||||||
|
|
||||||
# Ignore all test and documentation with "export-ignore".
|
# Ignore all test and documentation with "export-ignore".
|
||||||
|
/.github export-ignore
|
||||||
/.gitattributes export-ignore
|
/.gitattributes export-ignore
|
||||||
/.gitignore export-ignore
|
/.gitignore export-ignore
|
||||||
/phpunit.xml.dist export-ignore
|
/phpunit.xml.dist export-ignore
|
||||||
|
/phpunit.xml export-ignore
|
||||||
/tests export-ignore
|
/tests export-ignore
|
||||||
/.editorconfig export-ignore
|
/.editorconfig export-ignore
|
||||||
/.github export-ignore
|
/.styleci.yml export-ignore
|
||||||
/.assets export-ignore
|
/composer.lock export-ignore
|
||||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
0
.assets/ko-fi.png → .github/assets/ko-fi.png
vendored
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
143
.github/workflows/php.yml
vendored
@@ -1,50 +1,125 @@
|
|||||||
name: Tests
|
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow
|
||||||
|
|
||||||
|
name: "Tests"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: true
|
|
||||||
matrix:
|
|
||||||
php: [ 8.0, 8.1 ]
|
|
||||||
laravel: [ 9.* ]
|
|
||||||
dependency-version: [ prefer-stable, prefer-lowest ]
|
|
||||||
include:
|
|
||||||
- laravel: 9.*
|
|
||||||
testbench: 7.*
|
|
||||||
|
|
||||||
name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} - ${{ matrix.dependency-version }}
|
|
||||||
|
|
||||||
|
byte_level:
|
||||||
|
name: "0️⃣ Byte-level"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: "Checkout code"
|
||||||
uses: actions/checkout@v2
|
uses: "actions/checkout@v3"
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: "Check file permissions"
|
||||||
uses: shivammathur/setup-php@v2
|
run: |
|
||||||
|
test "$(find . -type f -not -path './.git/*' -executable)" == ""
|
||||||
|
- name: "Find non-printable ASCII characters"
|
||||||
|
run: |
|
||||||
|
! LC_ALL=C.UTF-8 find ./src -type f -name "*.php" -print0 | xargs -0 -- grep -PHn "[^ -~]"
|
||||||
|
syntax_errors:
|
||||||
|
name: "1️⃣ Syntax errors"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
steps:
|
||||||
|
- name: "Set up PHP"
|
||||||
|
uses: "shivammathur/setup-php@v2"
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php }}
|
php-version: "8.1"
|
||||||
|
tools: "parallel-lint"
|
||||||
|
|
||||||
|
- name: "Checkout code"
|
||||||
|
uses: "actions/checkout@v3"
|
||||||
|
|
||||||
|
- name: "Install dependencies"
|
||||||
|
uses: "ramsey/composer-install@v2"
|
||||||
|
with:
|
||||||
|
dependency-versions: "highest"
|
||||||
|
|
||||||
|
- name: "Check source code for syntax errors"
|
||||||
|
run: "composer exec -- parallel-lint src/"
|
||||||
|
|
||||||
|
unit_tests:
|
||||||
|
name: "2️⃣ Unit and Feature tests"
|
||||||
|
needs:
|
||||||
|
- "byte_level"
|
||||||
|
- "syntax_errors"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php-version:
|
||||||
|
- "8.1"
|
||||||
|
laravel-constrain:
|
||||||
|
- "9.*"
|
||||||
|
dependencies:
|
||||||
|
- "lowest"
|
||||||
|
- "highest"
|
||||||
|
steps:
|
||||||
|
- name: "Set up PHP"
|
||||||
|
uses: "shivammathur/setup-php@v2"
|
||||||
|
with:
|
||||||
|
php-version: "${{ matrix.php-version }}"
|
||||||
extensions: mbstring, intl
|
extensions: mbstring, intl
|
||||||
coverage: xdebug
|
coverage: xdebug
|
||||||
|
|
||||||
- name: Cache dependencies
|
- name: "Checkout code"
|
||||||
uses: actions/cache@v2
|
uses: "actions/checkout@v3"
|
||||||
|
|
||||||
|
- name: "Install dependencies"
|
||||||
|
uses: "ramsey/composer-install@v2"
|
||||||
with:
|
with:
|
||||||
path: ~/.composer/cache/files
|
dependency-versions: "${{ matrix.dependencies }}"
|
||||||
key: ${{ runner.os }}-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
|
|
||||||
restore-keys: ${{ runner.os }}-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: "Execute unit tests"
|
||||||
|
run: "composer run-script test"
|
||||||
|
|
||||||
|
- name: "Upload coverage to Codecov"
|
||||||
|
uses: "codecov/codecov-action@v2"
|
||||||
|
|
||||||
|
static_analysis:
|
||||||
|
name: "3️⃣ Static Analysis"
|
||||||
|
needs:
|
||||||
|
- "byte_level"
|
||||||
|
- "syntax_errors"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
steps:
|
||||||
|
- name: "Set up PHP"
|
||||||
|
uses: "shivammathur/setup-php@v2"
|
||||||
|
with:
|
||||||
|
php-version: "8.1"
|
||||||
|
tools: "phpstan"
|
||||||
|
|
||||||
|
- name: "Checkout code"
|
||||||
|
uses: "actions/checkout@v3"
|
||||||
|
|
||||||
|
- name: "Validate Composer configuration"
|
||||||
|
run: "composer validate --strict"
|
||||||
|
|
||||||
|
- name: "Install dependencies"
|
||||||
|
uses: "ramsey/composer-install@v2"
|
||||||
|
with:
|
||||||
|
dependency-versions: "highest"
|
||||||
|
|
||||||
|
- name: "Execute static analysis"
|
||||||
|
run: "composer exec -- phpstan analyze -l 5 src/"
|
||||||
|
|
||||||
|
exported_files:
|
||||||
|
name: "4️⃣ Exported files"
|
||||||
|
needs:
|
||||||
|
- "byte_level"
|
||||||
|
- "syntax_errors"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
steps:
|
||||||
|
- name: "Checkout code"
|
||||||
|
uses: "actions/checkout@v3"
|
||||||
|
|
||||||
|
- name: "Check exported files"
|
||||||
run: |
|
run: |
|
||||||
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-progress --no-update
|
EXPECTED="LICENSE.md,README.md,composer.json"
|
||||||
composer update --${{ matrix.dependency-version }} --prefer-dist --no-progress
|
CURRENT="$(git archive HEAD | tar --list --exclude="src" --exclude="src/*" --exclude=".stubs" --exclude=".stubs/*" --exclude="stubs" --exclude="stubs/*" --exclude="lang" --exclude="lang/*" --exclude="config" --exclude="config/*" --exclude="database" --exclude="database/*" --exclude="resources" --exclude="resources/*" --exclude="routes" --exclude="routes/*" | paste -s -d ",")"
|
||||||
- name: Run Tests
|
echo "CURRENT =${CURRENT}"
|
||||||
run: composer run-script test
|
echo "EXPECTED=${EXPECTED}"
|
||||||
|
test "${CURRENT}" == "${EXPECTED}"
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v2
|
|
||||||
|
|
||||||
|
|||||||
13
.gitignore
vendored
@@ -1,8 +1,7 @@
|
|||||||
.idea
|
/build
|
||||||
build
|
/vendor
|
||||||
composer.lock
|
/.idea
|
||||||
docs
|
.php-cs-fixer.cache
|
||||||
vendor
|
|
||||||
coverage
|
|
||||||
.phpunit.result.cache
|
.phpunit.result.cache
|
||||||
.vscode
|
composer.lock
|
||||||
|
phpunit.xml.bak
|
||||||
@@ -25,7 +25,7 @@ public function login(AssertedRequest $request)
|
|||||||
|
|
||||||
## Keep this package free
|
## Keep this package free
|
||||||
|
|
||||||
[](https://patreon.com/packagesforlaravel)[](https://ko-fi.com/DarkGhostHunter)[](https://www.buymeacoffee.com/darkghosthunter)[](https://www.paypal.com/paypalme/darkghosthunter)
|
[](https://patreon.com/packagesforlaravel)[](https://ko-fi.com/DarkGhostHunter)[](https://www.buymeacoffee.com/darkghosthunter)[](https://www.paypal.com/paypalme/darkghosthunter)
|
||||||
|
|
||||||
Your support allows me to keep this package free, up-to-date and maintainable. Alternatively, you can **[spread the word!](http://twitter.com/share?text=I%20am%20using%20this%20cool%20PHP%20package&url=https://github.com%2FLaragear%2FWebAuthn&hashtags=PHP,Laravel)**
|
Your support allows me to keep this package free, up-to-date and maintainable. Alternatively, you can **[spread the word!](http://twitter.com/share?text=I%20am%20using%20this%20cool%20PHP%20package&url=https://github.com%2FLaragear%2FWebAuthn&hashtags=PHP,Laravel)**
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class CreateAssertionChallenge
|
|||||||
$options = [];
|
$options = [];
|
||||||
|
|
||||||
if ($assertion->acceptedCredentials?->isNotEmpty()) {
|
if ($assertion->acceptedCredentials?->isNotEmpty()) {
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
$options['credentials'] = $assertion->acceptedCredentials->map->getKey()->toArray();
|
$options['credentials'] = $assertion->acceptedCredentials->map->getKey()->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,10 +36,11 @@ class MayRetrieveCredentialsIdForUser
|
|||||||
* Adapt all credentials into an `allowCredentials` digestible array.
|
* Adapt all credentials into an `allowCredentials` digestible array.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Database\Eloquent\Collection<int, \Laragear\WebAuthn\Models\WebAuthnCredential> $credentials
|
* @param \Illuminate\Database\Eloquent\Collection<int, \Laragear\WebAuthn\Models\WebAuthnCredential> $credentials
|
||||||
* @return \Illuminate\Support\Collection<int, array>
|
* @return \Illuminate\Support\Collection<int, array{id?: mixed, type: string, transports?: non-empty-array<int, string>}>
|
||||||
*/
|
*/
|
||||||
protected function parseCredentials(EloquentCollection $credentials): Collection
|
protected function parseCredentials(EloquentCollection $credentials): Collection
|
||||||
{
|
{
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
return $credentials->map(static function (WebAuthnCredential $credential): array {
|
return $credentials->map(static function (WebAuthnCredential $credential): array {
|
||||||
return array_filter([
|
return array_filter([
|
||||||
'id' => $credential->getKey(),
|
'id' => $credential->getKey(),
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ class CheckCredentialIsForUser
|
|||||||
*/
|
*/
|
||||||
protected function validateUser(AssertionValidation $validation): void
|
protected function validateUser(AssertionValidation $validation): void
|
||||||
{
|
{
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
if ($validation->credential->authenticatable()->isNot($validation->user)) {
|
if ($validation->credential->authenticatable()->isNot($validation->user)) {
|
||||||
throw AssertionException::make('User is not owner of the stored credential.');
|
throw AssertionException::make('User is not owner of the stored credential.');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use function unpack;
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright © 2021 Lukas Buchs
|
* Copyright (c) 2021 Lukas Buchs
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -76,10 +76,10 @@ class AuthenticatorData
|
|||||||
* @param string $relyingPartyIdHash
|
* @param string $relyingPartyIdHash
|
||||||
* @param object $flags
|
* @param object $flags
|
||||||
* @param int $counter
|
* @param int $counter
|
||||||
* @param object{aaguid: int|bool, credentialId: string, credentialPublicKey: string} $attestedCredentialData
|
* @param object $attestedCredentialData
|
||||||
* @param array $extensionData
|
* @param array $extensionData
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
final public function __construct(
|
||||||
public string $relyingPartyIdHash,
|
public string $relyingPartyIdHash,
|
||||||
public object $flags,
|
public object $flags,
|
||||||
public int $counter,
|
public int $counter,
|
||||||
@@ -366,13 +366,21 @@ class AuthenticatorData
|
|||||||
protected static function readFlags(string $binFlag): object
|
protected static function readFlags(string $binFlag): object
|
||||||
{
|
{
|
||||||
$flags = (object) [
|
$flags = (object) [
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
'bit_0' => (bool) ($binFlag & 1),
|
'bit_0' => (bool) ($binFlag & 1),
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
'bit_1' => (bool) ($binFlag & 2),
|
'bit_1' => (bool) ($binFlag & 2),
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
'bit_2' => (bool) ($binFlag & 4),
|
'bit_2' => (bool) ($binFlag & 4),
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
'bit_3' => (bool) ($binFlag & 8),
|
'bit_3' => (bool) ($binFlag & 8),
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
'bit_4' => (bool) ($binFlag & 16),
|
'bit_4' => (bool) ($binFlag & 16),
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
'bit_5' => (bool) ($binFlag & 32),
|
'bit_5' => (bool) ($binFlag & 32),
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
'bit_6' => (bool) ($binFlag & 64),
|
'bit_6' => (bool) ($binFlag & 64),
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
'bit_7' => (bool) ($binFlag & 128),
|
'bit_7' => (bool) ($binFlag & 128),
|
||||||
'userPresent' => false,
|
'userPresent' => false,
|
||||||
'userVerified' => false,
|
'userVerified' => false,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class AddUserDescriptor
|
|||||||
$config = $attestable->user->webAuthnData();
|
$config = $attestable->user->webAuthnData();
|
||||||
|
|
||||||
// Create a new User UUID if it doesn't existe already in the credentials.
|
// Create a new User UUID if it doesn't existe already in the credentials.
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
$config['id'] = $attestable->user->webAuthnCredentials()->value('user_id')
|
$config['id'] = $attestable->user->webAuthnCredentials()->value('user_id')
|
||||||
?: Str::uuid()->getHex()->toString();
|
?: Str::uuid()->getHex()->toString();
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class MayPreventDuplicateCredentials
|
|||||||
return $user
|
return $user
|
||||||
->webAuthnCredentials()
|
->webAuthnCredentials()
|
||||||
->get(['id', 'transports'])
|
->get(['id', 'transports'])
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
->map(static function (WebAuthnCredential $credential): array {
|
->map(static function (WebAuthnCredential $credential): array {
|
||||||
return array_filter([
|
return array_filter([
|
||||||
'id'=> $credential->getKey(),
|
'id'=> $credential->getKey(),
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use Laragear\WebAuthn\Attestation\AuthenticatorData;
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright © 2021 Lukas Buchs
|
* Copyright (c) 2021 Lukas Buchs
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ class WebAuthnUserProvider extends EloquentUserProvider
|
|||||||
/** @noinspection PhpIncompatibleReturnTypeInspection */
|
/** @noinspection PhpIncompatibleReturnTypeInspection */
|
||||||
return $this->newModelQuery()
|
return $this->newModelQuery()
|
||||||
->whereHas('webAuthnCredentials', static function (Builder $query) use ($credentials): void {
|
->whereHas('webAuthnCredentials', static function (Builder $query) use ($credentials): void {
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
$query->whereKey($credentials['id'])->whereEnabled();
|
$query->whereKey($credentials['id'])->whereEnabled();
|
||||||
})
|
})
|
||||||
->first();
|
->first();
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ use function unpack;
|
|||||||
* ---
|
* ---
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright © 2021 Lukas Buchs
|
* Copyright (c) 2021 Lukas Buchs
|
||||||
* Copyright © 2018 Thomas Bleeker (CBOR & ByteBuffer part)
|
* Copyright (c) 2018 Thomas Bleeker (CBOR & ByteBuffer part)
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -86,7 +86,7 @@ class ByteBuffer implements JsonSerializable, Jsonable, Stringable
|
|||||||
* @param string $binaryData
|
* @param string $binaryData
|
||||||
* @param int $dataLength
|
* @param int $dataLength
|
||||||
*/
|
*/
|
||||||
public function __construct(protected string $binaryData, protected int $dataLength = 0)
|
final public function __construct(protected string $binaryData, protected int $dataLength = 0)
|
||||||
{
|
{
|
||||||
$this->dataLength = strlen($binaryData);
|
$this->dataLength = strlen($binaryData);
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@ class ByteBuffer implements JsonSerializable, Jsonable, Stringable
|
|||||||
* Returns the value of a single unsigned 16-bit integer.
|
* Returns the value of a single unsigned 16-bit integer.
|
||||||
*
|
*
|
||||||
* @param int $offset
|
* @param int $offset
|
||||||
* @return mixed
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getUint16Val(int $offset = 0): int
|
public function getUint16Val(int $offset = 0): int
|
||||||
{
|
{
|
||||||
@@ -209,7 +209,7 @@ class ByteBuffer implements JsonSerializable, Jsonable, Stringable
|
|||||||
* Returns the value of a single unsigned 32-bit integer.
|
* Returns the value of a single unsigned 32-bit integer.
|
||||||
*
|
*
|
||||||
* @param int $offset
|
* @param int $offset
|
||||||
* @return mixed
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getUint32Val(int $offset = 0): int
|
public function getUint32Val(int $offset = 0): int
|
||||||
{
|
{
|
||||||
@@ -404,7 +404,7 @@ class ByteBuffer implements JsonSerializable, Jsonable, Stringable
|
|||||||
throw new InvalidArgumentException('ByteBuffer: Invalid base64 url string');
|
throw new InvalidArgumentException('ByteBuffer: Invalid base64 url string');
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ByteBuffer($bin);
|
return new static($bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -415,11 +415,14 @@ class ByteBuffer implements JsonSerializable, Jsonable, Stringable
|
|||||||
*/
|
*/
|
||||||
public static function fromBase64(string $base64): static
|
public static function fromBase64(string $base64): static
|
||||||
{
|
{
|
||||||
if (false === $bin = base64_decode($base64)) {
|
/** @var string|false $bin */
|
||||||
|
$bin = base64_decode($base64);
|
||||||
|
|
||||||
|
if (false === $bin) {
|
||||||
throw new InvalidArgumentException('ByteBuffer: Invalid base64 string');
|
throw new InvalidArgumentException('ByteBuffer: Invalid base64 string');
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ByteBuffer($bin);
|
return new static($bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ use function sprintf;
|
|||||||
* ---
|
* ---
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright © 2021 Lukas Buchs
|
* Copyright (c) 2021 Lukas Buchs
|
||||||
* Copyright © 2018 Thomas Bleeker (CBOR & ByteBuffer part)
|
* Copyright (c) 2018 Thomas Bleeker (CBOR & ByteBuffer part)
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -248,7 +248,7 @@ class CborDecoder
|
|||||||
* @param \Laragear\WebAuthn\ByteBuffer $buf
|
* @param \Laragear\WebAuthn\ByteBuffer $buf
|
||||||
* @param $offset
|
* @param $offset
|
||||||
* @return \Laragear\WebAuthn\ByteBuffer|array|bool|float|int|string|null
|
* @return \Laragear\WebAuthn\ByteBuffer|array|bool|float|int|string|null
|
||||||
* @throws \Laragear\WebAuthn\Exceptions\DataException
|
* @throws \Laragear\WebAuthn\Exceptions\DataException|\InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
protected static function parseItemData(
|
protected static function parseItemData(
|
||||||
int $type,
|
int $type,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class Challenge
|
|||||||
* @param bool $verify
|
* @param bool $verify
|
||||||
* @param array $properties
|
* @param array $properties
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
final public function __construct(
|
||||||
public ByteBuffer $data,
|
public ByteBuffer $data,
|
||||||
public int $timeout,
|
public int $timeout,
|
||||||
public bool $verify = true,
|
public bool $verify = true,
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ interface WebAuthnAuthenticatable
|
|||||||
/**
|
/**
|
||||||
* Returns a queryable relationship for its WebAuthn Credentials.
|
* Returns a queryable relationship for its WebAuthn Credentials.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\MorphMany&\Laragear\WebAuthn\Models\WebAuthnCredential
|
* @phpstan-ignore-next-line
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\MorphMany|\Laragear\WebAuthn\Models\WebAuthnCredential
|
||||||
*/
|
*/
|
||||||
public function webAuthnCredentials(): MorphMany;
|
public function webAuthnCredentials(): MorphMany;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class AssertionException extends ValidationException implements WebAuthnExceptio
|
|||||||
* Create a new Assertion Exception with the error message.
|
* Create a new Assertion Exception with the error message.
|
||||||
*
|
*
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @return \Laragear\WebAuthn\Exceptions\AssertionException
|
* @return static
|
||||||
*/
|
*/
|
||||||
public static function make(string $message): static
|
public static function make(string $message): static
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class AttestationException extends ValidationException implements WebAuthnExcept
|
|||||||
* Create a new Attestation Exception with the error message.
|
* Create a new Attestation Exception with the error message.
|
||||||
*
|
*
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @return \Laragear\WebAuthn\Exceptions\AttestationException
|
* @return static
|
||||||
*/
|
*/
|
||||||
public static function make(string $message): static
|
public static function make(string $message): static
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -48,15 +48,18 @@ class AssertedRequest extends FormRequest
|
|||||||
* Logs in the user for this assertion request.
|
* Logs in the user for this assertion request.
|
||||||
*
|
*
|
||||||
* @param string|null $guard
|
* @param string|null $guard
|
||||||
* @return \Laragear\WebAuthn\Contracts\WebAuthnAuthenticatable&\Illuminate\Contracts\Auth\Authenticatable|null
|
* @phpstan-ignore-next-line
|
||||||
|
* @return \Laragear\WebAuthn\Contracts\WebAuthnAuthenticatable|\Illuminate\Contracts\Auth\Authenticatable|null
|
||||||
*/
|
*/
|
||||||
public function login(string $guard = null, bool $remember = null, bool $destroySession = false): ?WebAuthnAuthenticatable
|
public function login(string $guard = null, bool $remember = null, bool $destroySession = false): ?WebAuthnAuthenticatable
|
||||||
{
|
{
|
||||||
|
/** @var \Illuminate\Contracts\Auth\StatefulGuard $auth */
|
||||||
$auth = Auth::guard($guard);
|
$auth = Auth::guard($guard);
|
||||||
|
|
||||||
if ($auth->attempt($this->validated(), $remember ?? $this->hasRemember())) {
|
if ($auth->attempt($this->validated(), $remember ?? $this->hasRemember())) {
|
||||||
$this->session()->regenerate($destroySession);
|
$this->session()->regenerate($destroySession);
|
||||||
|
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
return $auth->user();
|
return $auth->user();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,9 @@ class AssertionRequest extends FormRequest
|
|||||||
// retrieve by its ID, otherwise we will fall back to credentials. Once done, we
|
// retrieve by its ID, otherwise we will fall back to credentials. Once done, we
|
||||||
// will check it uses WebAuthn if is not null, otherwise we'll fail miserably.
|
// will check it uses WebAuthn if is not null, otherwise we'll fail miserably.
|
||||||
$user = is_string($credentials) || is_int($credentials)
|
$user = is_string($credentials) || is_int($credentials)
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
? Auth::guard($this->guard)->getProvider()->retrieveById($credentials)
|
? Auth::guard($this->guard)->getProvider()->retrieveById($credentials)
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
: Auth::guard($this->guard)->getProvider()->retrieveByCredentials($credentials);
|
: Auth::guard($this->guard)->getProvider()->retrieveByCredentials($credentials);
|
||||||
|
|
||||||
if ($user && ! $user instanceof WebAuthnAuthenticatable) {
|
if ($user && ! $user instanceof WebAuthnAuthenticatable) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use Laragear\WebAuthn\Events\CredentialDisabled;
|
|||||||
use Laragear\WebAuthn\Events\CredentialEnabled;
|
use Laragear\WebAuthn\Events\CredentialEnabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @mixin \Illuminate\Database\Eloquent\Builder<\Laragear\WebAuthn\Models\WebAuthnCredential>
|
* @mixin \Illuminate\Database\Eloquent\Builder
|
||||||
*
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|static query()
|
* @method static \Illuminate\Database\Eloquent\Builder|static query()
|
||||||
* @method \Illuminate\Database\Eloquent\Builder|static newQuery()
|
* @method \Illuminate\Database\Eloquent\Builder|static newQuery()
|
||||||
@@ -22,10 +22,10 @@ use Laragear\WebAuthn\Events\CredentialEnabled;
|
|||||||
* @method \Laragear\WebAuthn\Models\WebAuthnCredential firstOr($columns = ['*'], \Closure $callback = null)
|
* @method \Laragear\WebAuthn\Models\WebAuthnCredential firstOr($columns = ['*'], \Closure $callback = null)
|
||||||
* @method \Laragear\WebAuthn\Models\WebAuthnCredential firstWhere($column, $operator = null, $value = null, $boolean = 'and')
|
* @method \Laragear\WebAuthn\Models\WebAuthnCredential firstWhere($column, $operator = null, $value = null, $boolean = 'and')
|
||||||
* @method \Laragear\WebAuthn\Models\WebAuthnCredential updateOrCreate(array $attributes, array $values = [])
|
* @method \Laragear\WebAuthn\Models\WebAuthnCredential updateOrCreate(array $attributes, array $values = [])
|
||||||
* @method static|null first($columns = ['*'])
|
* @method ?static first($columns = ['*'])
|
||||||
* @method static static findOrFail($id, $columns = ['*'])
|
* @method static static findOrFail($id, $columns = ['*'])
|
||||||
* @method static static findOrNew($id, $columns = ['*'])
|
* @method static static findOrNew($id, $columns = ['*'])
|
||||||
* @method static static|null find($id, $columns = ['*'])
|
* @method static ?null find($id, $columns = ['*'])
|
||||||
*
|
*
|
||||||
* @property-read string $id
|
* @property-read string $id
|
||||||
*
|
*
|
||||||
@@ -98,7 +98,8 @@ class WebAuthnCredential extends Model
|
|||||||
protected $visible = ['id', 'origin', 'alias', 'aaguid', 'attestation_format', 'disabled_at', 'is_enabled'];
|
protected $visible = ['id', 'origin', 'alias', 'aaguid', 'attestation_format', 'disabled_at', 'is_enabled'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo&\Laragear\WebAuthn\Contracts\WebAuthnAuthenticatable
|
* @phpstan-ignore-next-line
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\MorphTo|\Laragear\WebAuthn\Contracts\WebAuthnAuthenticatable
|
||||||
*/
|
*/
|
||||||
public function authenticatable(): MorphTo
|
public function authenticatable(): MorphTo
|
||||||
{
|
{
|
||||||
@@ -113,6 +114,7 @@ class WebAuthnCredential extends Model
|
|||||||
*/
|
*/
|
||||||
protected function scopeWhereEnabled(Builder $query): Builder
|
protected function scopeWhereEnabled(Builder $query): Builder
|
||||||
{
|
{
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
return $query->whereNull('disabled_at');
|
return $query->whereNull('disabled_at');
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -123,6 +125,7 @@ class WebAuthnCredential extends Model
|
|||||||
*/
|
*/
|
||||||
protected function scopeWhereDisabled(Builder $query): Builder
|
protected function scopeWhereDisabled(Builder $query): Builder
|
||||||
{
|
{
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
return $query->whereNotNull('disabled_at');
|
return $query->whereNotNull('disabled_at');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ class WebAuthnServiceProvider extends ServiceProvider
|
|||||||
if ($this->app->runningInConsole()) {
|
if ($this->app->runningInConsole()) {
|
||||||
$this->publishesMigrations(static::MIGRATIONS);
|
$this->publishesMigrations(static::MIGRATIONS);
|
||||||
$this->publishes([static::ROUTES => $this->app->basePath('routes/webauthn.php')], 'routes');
|
$this->publishes([static::ROUTES => $this->app->basePath('routes/webauthn.php')], 'routes');
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
$this->publishes([static::CONTROLLERS => $this->app->path('Http/Controllers/WebAuthn')], 'controllers');
|
$this->publishes([static::CONTROLLERS => $this->app->path('Http/Controllers/WebAuthn')], 'controllers');
|
||||||
$this->publishes([static::JS => $this->app->resourcePath('js/vendor/webauthn')], 'js');
|
$this->publishes([static::JS => $this->app->resourcePath('js/vendor/webauthn')], 'js');
|
||||||
}
|
}
|
||||||
|
|||||||