mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-28 17:01:16 +00:00
Add remember me check for passkeys
This commit is contained in:
Generated
+1
-1
@@ -15371,5 +15371,5 @@
|
|||||||
"ext-zlib": "*"
|
"ext-zlib": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": {},
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.6.0"
|
"plugin-api-version": "2.9.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ Alpine.data('passkeyLogin', () => ({
|
|||||||
supported: false,
|
supported: false,
|
||||||
busy: false,
|
busy: false,
|
||||||
error: '',
|
error: '',
|
||||||
|
remember: false,
|
||||||
showCreateHint: false,
|
showCreateHint: false,
|
||||||
hasAutoPrompted: false,
|
hasAutoPrompted: false,
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ Alpine.data('passkeyLogin', () => ({
|
|||||||
// If backend already reported an invalid passkey login attempt,
|
// If backend already reported an invalid passkey login attempt,
|
||||||
// immediately show the "sign in first, then create passkey" guidance.
|
// immediately show the "sign in first, then create passkey" guidance.
|
||||||
this.showCreateHint = this.$el.dataset.serverPasskeyError === '1';
|
this.showCreateHint = this.$el.dataset.serverPasskeyError === '1';
|
||||||
|
this.remember = this.$el.dataset.rememberDefault === '1';
|
||||||
|
|
||||||
const shouldAutoPrompt = this.$el.dataset.autoPrompt === '1';
|
const shouldAutoPrompt = this.$el.dataset.autoPrompt === '1';
|
||||||
if (this.supported && shouldAutoPrompt && !this.showCreateHint) {
|
if (this.supported && shouldAutoPrompt && !this.showCreateHint) {
|
||||||
@@ -57,6 +59,7 @@ Alpine.data('passkeyLogin', () => ({
|
|||||||
optionsJSON: optionsJson,
|
optionsJSON: optionsJson,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.$refs.remember.value = this.remember ? '1' : '0';
|
||||||
this.$refs.response.value = JSON.stringify(startAuthenticationResponse);
|
this.$refs.response.value = JSON.stringify(startAuthenticationResponse);
|
||||||
document.getElementById('passkey-login-form')?.submit();
|
document.getElementById('passkey-login-form')?.submit();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
data-options-url="{{ route('passkeys.authentication_options') }}"
|
data-options-url="{{ route('passkeys.authentication_options') }}"
|
||||||
data-server-passkey-error="{{ session('authenticatePasskey::reason') === 'invalid_passkey' ? '1' : '0' }}"
|
data-server-passkey-error="{{ session('authenticatePasskey::reason') === 'invalid_passkey' ? '1' : '0' }}"
|
||||||
data-auto-prompt="{{ ($autoPromptPasskey ?? true) ? '1' : '0' }}"
|
data-auto-prompt="{{ ($autoPromptPasskey ?? true) ? '1' : '0' }}"
|
||||||
|
data-remember-default="{{ old('rememberme') ? '1' : '0' }}"
|
||||||
data-captcha-enabled="{{ \App\Support\CaptchaHelper::isEnabled() ? '1' : '0' }}"
|
data-captcha-enabled="{{ \App\Support\CaptchaHelper::isEnabled() ? '1' : '0' }}"
|
||||||
data-captcha-field="{{ \App\Support\CaptchaHelper::isEnabled() ? \App\Support\CaptchaHelper::getResponseFieldName() : '' }}"
|
data-captcha-field="{{ \App\Support\CaptchaHelper::isEnabled() ? \App\Support\CaptchaHelper::getResponseFieldName() : '' }}"
|
||||||
class="mt-6"
|
class="mt-6"
|
||||||
@@ -26,6 +27,18 @@
|
|||||||
<input type="hidden" name="g-recaptcha-response" x-ref="recaptchaResponse" value="">
|
<input type="hidden" name="g-recaptcha-response" x-ref="recaptchaResponse" value="">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<div class="mt-4 flex items-center">
|
||||||
|
<input
|
||||||
|
id="passkey-remember"
|
||||||
|
x-model="remember"
|
||||||
|
type="checkbox"
|
||||||
|
class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:text-blue-400"
|
||||||
|
>
|
||||||
|
<label for="passkey-remember" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">
|
||||||
|
Remember me
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@click="authenticate()"
|
@click="authenticate()"
|
||||||
|
|||||||
@@ -70,6 +70,36 @@ class PasskeyAuthenticationTest extends TestCase
|
|||||||
Event::assertDispatched(UserLoggedIn::class);
|
Event::assertDispatched(UserLoggedIn::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_passkey_authentication_with_remember_sets_remember_token(): void
|
||||||
|
{
|
||||||
|
Event::fake([UserLoggedIn::class]);
|
||||||
|
$user = $this->createUser('passkey-remember@example.test');
|
||||||
|
|
||||||
|
$passkey = new Passkey;
|
||||||
|
$passkey->setRawAttributes([
|
||||||
|
'id' => 3,
|
||||||
|
'authenticatable_id' => $user->id,
|
||||||
|
'name' => 'Desktop',
|
||||||
|
'credential_id' => 'credential-3',
|
||||||
|
'data' => '{}',
|
||||||
|
], true);
|
||||||
|
$passkey->setRelation('authenticatable', $user);
|
||||||
|
|
||||||
|
FakeFindPasskeyAction::$passkey = $passkey;
|
||||||
|
config()->set('passkeys.actions.find_passkey', FakeFindPasskeyAction::class);
|
||||||
|
|
||||||
|
$this
|
||||||
|
->withSession(['passkey-authentication-options' => '{}'])
|
||||||
|
->post(route('passkeys.login'), [
|
||||||
|
'start_authentication_response' => json_encode(['id' => 'credential-3'], JSON_THROW_ON_ERROR),
|
||||||
|
'remember' => true,
|
||||||
|
])
|
||||||
|
->assertRedirect('/');
|
||||||
|
|
||||||
|
$this->assertAuthenticatedAs($user);
|
||||||
|
$this->assertNotNull($user->fresh()?->remember_token);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_unverified_users_cannot_authenticate_with_passkeys(): void
|
public function test_unverified_users_cannot_authenticate_with_passkeys(): void
|
||||||
{
|
{
|
||||||
$user = $this->createUser('unverified@example.test', false);
|
$user = $this->createUser('unverified@example.test', false);
|
||||||
|
|||||||
Reference in New Issue
Block a user